summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/BUILD.gn12
-rw-r--r--cc/cc.gyp4
-rw-r--r--cc/cc_tests.gyp8
-rw-r--r--cc/debug/benchmark_instrumentation.h2
-rw-r--r--cc/scheduler/scheduler_state_machine_unittest.cc4
-rw-r--r--cc/test/layer_tree_test.cc298
-rw-r--r--cc/test/layer_tree_test.h136
-rw-r--r--cc/test/proxy_impl_for_test.cc163
-rw-r--r--cc/test/proxy_impl_for_test.h73
-rw-r--r--cc/test/proxy_main_for_test.cc104
-rw-r--r--cc/test/proxy_main_for_test.h56
-rw-r--r--cc/test/test_hooks.cc28
-rw-r--r--cc/test/test_hooks.h139
-rw-r--r--cc/test/threaded_channel_for_test.cc36
-rw-r--r--cc/test/threaded_channel_for_test.h38
-rw-r--r--cc/trees/channel_main.h18
-rw-r--r--cc/trees/layer_tree_host.cc8
-rw-r--r--cc/trees/layer_tree_host_unittest.cc1
-rw-r--r--cc/trees/layer_tree_host_unittest_proxy.cc215
-rw-r--r--cc/trees/proxy_impl.cc684
-rw-r--r--cc/trees/proxy_impl.h190
-rw-r--r--cc/trees/proxy_main.cc465
-rw-r--r--cc/trees/proxy_main.h167
-rw-r--r--cc/trees/thread_proxy.cc1190
-rw-r--r--cc/trees/thread_proxy.h333
-rw-r--r--cc/trees/threaded_channel.cc305
-rw-r--r--cc/trees/threaded_channel.h110
-rw-r--r--cc/trees/threaded_channel_unittest.cc21
28 files changed, 2575 insertions, 2233 deletions
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index df0083a..3be4ebb 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -502,7 +502,9 @@ component("cc") {
"trees/proxy.h",
"trees/proxy_common.cc",
"trees/proxy_common.h",
+ "trees/proxy_impl.cc",
"trees/proxy_impl.h",
+ "trees/proxy_main.cc",
"trees/proxy_main.h",
"trees/remote_proto_channel.h",
"trees/scoped_abort_remaining_swap_promises.h",
@@ -512,8 +514,6 @@ component("cc") {
"trees/swap_promise_monitor.h",
"trees/task_runner_provider.cc",
"trees/task_runner_provider.h",
- "trees/thread_proxy.cc",
- "trees/thread_proxy.h",
"trees/threaded_channel.cc",
"trees/threaded_channel.h",
"trees/tree_synchronizer.cc",
@@ -655,6 +655,10 @@ source_set("test_support") {
"test/pixel_test_software_output_device.h",
"test/pixel_test_utils.cc",
"test/pixel_test_utils.h",
+ "test/proxy_impl_for_test.cc",
+ "test/proxy_impl_for_test.h",
+ "test/proxy_main_for_test.cc",
+ "test/proxy_main_for_test.h",
"test/render_pass_test_utils.cc",
"test/render_pass_test_utils.h",
"test/scheduler_test_common.cc",
@@ -677,6 +681,8 @@ source_set("test_support") {
"test/test_gles2_interface.h",
"test/test_gpu_memory_buffer_manager.cc",
"test/test_gpu_memory_buffer_manager.h",
+ "test/test_hooks.cc",
+ "test/test_hooks.h",
"test/test_image_factory.cc",
"test/test_image_factory.h",
"test/test_in_process_context_provider.cc",
@@ -692,6 +698,8 @@ source_set("test_support") {
"test/test_tile_priorities.h",
"test/test_web_graphics_context_3d.cc",
"test/test_web_graphics_context_3d.h",
+ "test/threaded_channel_for_test.cc",
+ "test/threaded_channel_for_test.h",
]
configs += [ "//build/config:precompiled_headers" ]
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 508ff1c..7bce8be 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -564,7 +564,9 @@
'trees/proxy.h',
'trees/proxy_common.cc',
'trees/proxy_common.h',
+ 'trees/proxy_impl.cc',
'trees/proxy_impl.h',
+ 'trees/proxy_main.cc',
'trees/proxy_main.h',
'trees/remote_proto_channel.h',
'trees/scoped_abort_remaining_swap_promises.h',
@@ -572,8 +574,6 @@
'trees/single_thread_proxy.h',
'trees/swap_promise_monitor.cc',
'trees/swap_promise_monitor.h',
- 'trees/thread_proxy.cc',
- 'trees/thread_proxy.h',
'trees/task_runner_provider.cc',
'trees/task_runner_provider.h',
'trees/threaded_channel.cc',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 5332133..8ce17e2 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -258,6 +258,10 @@
'test/pixel_test_software_output_device.h',
'test/pixel_test_utils.cc',
'test/pixel_test_utils.h',
+ 'test/proxy_impl_for_test.cc',
+ 'test/proxy_impl_for_test.h',
+ 'test/proxy_main_for_test.cc',
+ 'test/proxy_main_for_test.h',
'test/render_pass_test_utils.cc',
'test/render_pass_test_utils.h',
'test/scheduler_test_common.cc',
@@ -280,6 +284,8 @@
'test/test_gles2_interface.h',
'test/test_gpu_memory_buffer_manager.cc',
'test/test_gpu_memory_buffer_manager.h',
+ 'test/test_hooks.cc',
+ 'test/test_hooks.h',
'test/test_image_factory.cc',
'test/test_image_factory.h',
'test/test_in_process_context_provider.cc',
@@ -295,6 +301,8 @@
'test/test_tile_priorities.h',
'test/test_web_graphics_context_3d.cc',
'test/test_web_graphics_context_3d.h',
+ 'test/threaded_channel_for_test.cc',
+ 'test/threaded_channel_for_test.h',
],
},
'targets': [
diff --git a/cc/debug/benchmark_instrumentation.h b/cc/debug/benchmark_instrumentation.h
index 944ac66..99cfa21 100644
--- a/cc/debug/benchmark_instrumentation.h
+++ b/cc/debug/benchmark_instrumentation.h
@@ -20,6 +20,8 @@ const char kCategory[] = "cc,benchmark";
const char kBeginFrameId[] = "begin_frame_id";
} // namespace internal
+// TODO(khushalsagar): Fix these names for the telemetry benchmarks.
+// See crbug/567993.
const char kSendBeginFrame[] = "ThreadProxy::ScheduledActionSendBeginMainFrame";
const char kDoBeginFrame[] = "ThreadProxy::BeginMainFrame";
diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc
index 8999b2f..44d16c1 100644
--- a/cc/scheduler/scheduler_state_machine_unittest.cc
+++ b/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -1228,7 +1228,7 @@ TEST(SchedulerStateMachineTest, TestNoRequestOutputSurfaceWhenInvisible) {
SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
}
-// See ThreadProxy::BeginMainFrame "EarlyOut_NotVisible" /
+// See ProxyMain::BeginMainFrame "EarlyOut_NotVisible" /
// "EarlyOut_OutputSurfaceLost" cases.
TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseInvisible) {
SchedulerSettings default_scheduler_settings;
@@ -1282,7 +1282,7 @@ TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseInvisible) {
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
}
-// See ThreadProxy::BeginMainFrame "EarlyOut_NoUpdates" case.
+// See ProxyMain::BeginMainFrame "EarlyOut_NoUpdates" case.
TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseCommitNotNeeded) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index a99e2f2..d68ec67 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -30,8 +30,10 @@
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/proxy_impl.h"
+#include "cc/trees/proxy_main.h"
#include "cc/trees/single_thread_proxy.h"
-#include "cc/trees/thread_proxy.h"
+#include "cc/trees/threaded_channel.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/gfx/geometry/size_conversions.h"
@@ -93,254 +95,8 @@ void CreateVirtualViewportLayers(Layer* root_layer,
layer_settings);
}
-TestHooks::TestHooks() {}
-
-TestHooks::~TestHooks() {}
-
-DrawResult TestHooks::PrepareToDrawOnThread(
- LayerTreeHostImpl* host_impl,
- LayerTreeHostImpl::FrameData* frame_data,
- DrawResult draw_result) {
- return draw_result;
-}
-
-void TestHooks::CreateResourceAndTileTaskWorkerPool(
- LayerTreeHostImpl* host_impl,
- scoped_ptr<TileTaskWorkerPool>* tile_task_worker_pool,
- scoped_ptr<ResourcePool>* resource_pool) {
- host_impl->LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool(
- tile_task_worker_pool, resource_pool);
-}
-
-// Adapts ThreadProxy for test. Injects test hooks for testing.
-class ThreadProxyForTest : public ThreadProxy {
- public:
- static scoped_ptr<Proxy> Create(
- TestHooks* test_hooks,
- LayerTreeHost* host,
- TaskRunnerProvider* task_runner_provider,
- scoped_ptr<BeginFrameSource> external_begin_frame_source) {
- return make_scoped_ptr(
- new ThreadProxyForTest(test_hooks, host, task_runner_provider,
- std::move(external_begin_frame_source)));
- }
-
- ~ThreadProxyForTest() override {}
-
- private:
- TestHooks* test_hooks_;
-
- void SetNeedsUpdateLayers() override {
- ThreadProxy::SetNeedsUpdateLayers();
- test_hooks_->DidSetNeedsUpdateLayers();
- }
-
- void ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) override {
- test_hooks_->ScheduledActionWillSendBeginMainFrame();
- ThreadProxy::ScheduledActionSendBeginMainFrame(args);
- test_hooks_->ScheduledActionSendBeginMainFrame();
- }
-
- DrawResult ScheduledActionDrawAndSwapIfPossible() override {
- DrawResult result = ThreadProxy::ScheduledActionDrawAndSwapIfPossible();
- test_hooks_->ScheduledActionDrawAndSwapIfPossible();
- return result;
- }
-
- void ScheduledActionCommit() override {
- ThreadProxy::ScheduledActionCommit();
- test_hooks_->ScheduledActionCommit();
- }
-
- void ScheduledActionBeginOutputSurfaceCreation() override {
- ThreadProxy::ScheduledActionBeginOutputSurfaceCreation();
- test_hooks_->ScheduledActionBeginOutputSurfaceCreation();
- }
-
- void ScheduledActionPrepareTiles() override {
- ThreadProxy::ScheduledActionPrepareTiles();
- test_hooks_->ScheduledActionPrepareTiles();
- }
-
- void ScheduledActionInvalidateOutputSurface() override {
- ThreadProxy::ScheduledActionInvalidateOutputSurface();
- test_hooks_->ScheduledActionInvalidateOutputSurface();
- }
-
- void SendBeginMainFrameNotExpectedSoon() override {
- ThreadProxy::SendBeginMainFrameNotExpectedSoon();
- test_hooks_->SendBeginMainFrameNotExpectedSoon();
- }
-
- void DidActivateSyncTree() override {
- ThreadProxy::DidActivateSyncTree();
- test_hooks_->DidActivateSyncTree();
- }
-
- void SetThrottleFrameProductionOnImpl(bool throttle) override {
- test_hooks_->SetThrottleFrameProductionOnImpl(throttle);
- ThreadProxy::SetThrottleFrameProductionOnImpl(throttle);
- }
-
- void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) override {
- test_hooks_->InitializeOutputSurfaceOnImpl(output_surface);
- ThreadProxy::InitializeOutputSurfaceOnImpl(output_surface);
- }
-
- void MainThreadHasStoppedFlingingOnImpl() override {
- test_hooks_->MainThreadHasStoppedFlingingOnImpl();
- ThreadProxy::MainThreadHasStoppedFlingingOnImpl();
- }
-
- void SetInputThrottledUntilCommitOnImpl(bool is_throttled) override {
- test_hooks_->SetInputThrottledUntilCommitOnImpl(is_throttled);
- ThreadProxy::SetInputThrottledUntilCommitOnImpl(is_throttled);
- }
-
- void UpdateTopControlsStateOnImpl(TopControlsState constraints,
- TopControlsState current,
- bool animate) override {
- test_hooks_->UpdateTopControlsStateOnImpl(constraints, current, animate);
- ThreadProxy::UpdateTopControlsStateOnImpl(constraints, current, animate);
- }
-
- void SetDeferCommitsOnImpl(bool defer_commits) const override {
- test_hooks_->SetDeferCommitsOnImpl(defer_commits);
- ThreadProxy::SetDeferCommitsOnImpl(defer_commits);
- }
-
- void BeginMainFrameAbortedOnImpl(
- CommitEarlyOutReason reason,
- base::TimeTicks main_thread_start_time) override {
- test_hooks_->BeginMainFrameAbortedOnImpl(reason);
- ThreadProxy::BeginMainFrameAbortedOnImpl(reason, main_thread_start_time);
- }
-
- void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) override {
- test_hooks_->SetNeedsRedrawOnImpl(damage_rect);
- ThreadProxy::SetNeedsRedrawOnImpl(damage_rect);
- };
-
- void SetNeedsCommitOnImpl() override {
- test_hooks_->SetNeedsCommitOnImpl();
- ThreadProxy::SetNeedsCommitOnImpl();
- }
-
- void FinishAllRenderingOnImpl(CompletionEvent* completion) override {
- test_hooks_->FinishAllRenderingOnImpl();
- ThreadProxy::FinishAllRenderingOnImpl(completion);
- };
-
- void SetVisibleOnImpl(bool visible) override {
- test_hooks_->SetVisibleOnImpl(visible);
- ThreadProxy::SetVisibleOnImpl(visible);
- }
-
- void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) override {
- test_hooks_->ReleaseOutputSurfaceOnImpl();
- ThreadProxy::ReleaseOutputSurfaceOnImpl(completion);
- }
-
- void FinishGLOnImpl(CompletionEvent* completion) override {
- test_hooks_->FinishGLOnImpl();
- ThreadProxy::FinishGLOnImpl(completion);
- }
-
- void StartCommitOnImpl(CompletionEvent* completion,
- LayerTreeHost* layer_tree_host,
- base::TimeTicks main_thread_start_time,
- bool hold_commit_for_activation) override {
- test_hooks_->StartCommitOnImpl();
- ThreadProxy::StartCommitOnImpl(completion, layer_tree_host,
- main_thread_start_time,
- hold_commit_for_activation);
- }
-
- void InitializeImplOnImpl(CompletionEvent* completion,
- LayerTreeHost* layer_tree_host) override {
- ThreadProxy::InitializeImplOnImpl(completion, layer_tree_host);
- test_hooks_->InitializeImplOnImpl();
- }
-
- void LayerTreeHostClosedOnImpl(CompletionEvent* completion) override {
- test_hooks_->WillCloseLayerTreeHostOnImpl();
- ThreadProxy::LayerTreeHostClosedOnImpl(completion);
- }
-
- void DidCompleteSwapBuffers() override {
- test_hooks_->ReceivedDidCompleteSwapBuffers();
- ThreadProxy::DidCompleteSwapBuffers();
- }
-
- void SetRendererCapabilitiesMainCopy(
- const RendererCapabilities& capabilities) override {
- test_hooks_->ReceivedSetRendererCapabilitiesMainCopy(capabilities);
- ThreadProxy::SetRendererCapabilitiesMainCopy(capabilities);
- }
-
- void BeginMainFrameNotExpectedSoon() override {
- test_hooks_->ReceivedBeginMainFrameNotExpectedSoon();
- ThreadProxy::BeginMainFrameNotExpectedSoon();
- }
-
- void DidCommitAndDrawFrame() override {
- test_hooks_->ReceivedDidCommitAndDrawFrame();
- ThreadProxy::DidCommitAndDrawFrame();
- }
-
- void SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) override {
- test_hooks_->ReceivedSetAnimationEvents();
- ThreadProxy::SetAnimationEvents(std::move(events));
- }
-
- void DidLoseOutputSurface() override {
- test_hooks_->ReceivedDidLoseOutputSurface();
- ThreadProxy::DidLoseOutputSurface();
- }
-
- void RequestNewOutputSurface() override {
- test_hooks_->ReceivedRequestNewOutputSurface();
- ThreadProxy::RequestNewOutputSurface();
- }
-
- void DidInitializeOutputSurface(
- bool success,
- const RendererCapabilities& capabilities) override {
- test_hooks_->ReceivedDidInitializeOutputSurface(success, capabilities);
- ThreadProxy::DidInitializeOutputSurface(success, capabilities);
- }
-
- void DidCompletePageScaleAnimation() override {
- test_hooks_->ReceivedDidCompletePageScaleAnimation();
- ThreadProxy::DidCompletePageScaleAnimation();
- }
-
- void PostFrameTimingEventsOnMain(
- scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
- scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
- override {
- test_hooks_->ReceivedPostFrameTimingEventsOnMain();
- ThreadProxy::PostFrameTimingEventsOnMain(std::move(composite_events),
- std::move(main_frame_events));
- }
-
- void BeginMainFrame(scoped_ptr<BeginMainFrameAndCommitState>
- begin_main_frame_state) override {
- test_hooks_->ReceivedBeginMainFrame();
- ThreadProxy::BeginMainFrame(std::move(begin_main_frame_state));
- };
-
- ThreadProxyForTest(TestHooks* test_hooks,
- LayerTreeHost* host,
- TaskRunnerProvider* task_runner_provider,
- scoped_ptr<BeginFrameSource> external_begin_frame_source)
- : ThreadProxy(host,
- task_runner_provider,
- std::move(external_begin_frame_source)),
- test_hooks_(test_hooks) {}
-};
-
-// Adapts SingleThreadProxy for test. Injects test hooks for testing.
+// Creates a SingleThreadProxy that notifies the supplied |test_hooks| of
+// various actions.
class SingleThreadProxyForTest : public SingleThreadProxy {
public:
static scoped_ptr<Proxy> Create(
@@ -357,7 +113,17 @@ class SingleThreadProxyForTest : public SingleThreadProxy {
~SingleThreadProxyForTest() override {}
private:
- TestHooks* test_hooks_;
+ SingleThreadProxyForTest(
+ TestHooks* test_hooks,
+ LayerTreeHost* host,
+ LayerTreeHostSingleThreadClient* client,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source)
+ : SingleThreadProxy(host,
+ client,
+ task_runner_provider,
+ std::move(external_begin_frame_source)),
+ test_hooks_(test_hooks) {}
void ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) override {
test_hooks_->ScheduledActionWillSendBeginMainFrame();
@@ -397,17 +163,7 @@ class SingleThreadProxyForTest : public SingleThreadProxy {
test_hooks_->SendBeginMainFrameNotExpectedSoon();
}
- SingleThreadProxyForTest(
- TestHooks* test_hooks,
- LayerTreeHost* host,
- LayerTreeHostSingleThreadClient* client,
- TaskRunnerProvider* task_runner_provider,
- scoped_ptr<BeginFrameSource> external_begin_frame_source)
- : SingleThreadProxy(host,
- client,
- task_runner_provider,
- std::move(external_begin_frame_source)),
- test_hooks_(test_hooks) {}
+ TestHooks* test_hooks_;
};
// Adapts LayerTreeHostImpl for test. Runs real code, then invokes test hooks.
@@ -700,9 +456,10 @@ class LayerTreeHostForTesting : public LayerTreeHost {
scoped_ptr<Proxy> proxy;
if (mode == CompositorMode::Threaded) {
DCHECK(impl_task_runner.get());
- proxy = ThreadProxyForTest::Create(
+ scoped_ptr<ProxyMain> proxy_main = ProxyMainForTest::CreateThreaded(
test_hooks, layer_tree_host.get(), task_runner_provider.get(),
std::move(external_begin_frame_source));
+ proxy = std::move(proxy_main);
} else {
proxy = SingleThreadProxyForTest::Create(
test_hooks, layer_tree_host.get(), client, task_runner_provider.get(),
@@ -1161,4 +918,21 @@ LayerTreeHost* LayerTreeTest::layer_tree_host() {
return layer_tree_host_.get();
}
+ProxyMainForTest* LayerTreeTest::GetProxyMainForTest() const {
+ DCHECK(HasImplThread());
+ return static_cast<ProxyMainForTest*>(proxy());
+}
+
+ProxyImplForTest* LayerTreeTest::GetProxyImplForTest() const {
+ DCHECK(HasImplThread());
+ ThreadedChannel* threaded_channel =
+ static_cast<ThreadedChannel*>(GetProxyMainForTest()->channel_main());
+ ProxyImpl* proxy_impl = threaded_channel->GetProxyImplForTesting();
+
+ // We check for null ProxyImpl since ProxyImpl exists in the ThreadedChannel
+ // only after it is initialized.
+ DCHECK(proxy_impl);
+ return static_cast<ProxyImplForTest*>(proxy_impl);
+}
+
} // namespace cc
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index d727ae6..ea509d5 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -9,6 +9,9 @@
#include "base/threading/thread.h"
#include "cc/animation/animation_delegate.h"
#include "cc/layers/layer_settings.h"
+#include "cc/test/proxy_impl_for_test.h"
+#include "cc/test/proxy_main_for_test.h"
+#include "cc/test/test_hooks.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -46,130 +49,6 @@ void CreateVirtualViewportLayers(Layer* root_layer,
LayerTreeHost* host,
const LayerSettings& layer_settings);
-// Used by test stubs to notify the test when something interesting happens.
-class TestHooks : public AnimationDelegate {
- public:
- TestHooks();
- ~TestHooks() override;
-
- void ReadSettings(const LayerTreeSettings& settings);
-
- virtual void CreateResourceAndTileTaskWorkerPool(
- LayerTreeHostImpl* host_impl,
- scoped_ptr<TileTaskWorkerPool>* tile_task_worker_pool,
- scoped_ptr<ResourcePool>* resource_pool);
- virtual void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
- const BeginFrameArgs& args) {}
- virtual void DidFinishImplFrameOnThread(LayerTreeHostImpl* host_impl) {}
- virtual void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl,
- CommitEarlyOutReason reason) {}
- virtual void WillPrepareTiles(LayerTreeHostImpl* host_impl) {}
- virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) {}
- virtual void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) {}
- virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) {}
- virtual void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) {}
- virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) {}
- virtual void InitializedRendererOnThread(LayerTreeHostImpl* host_impl,
- bool success) {}
- virtual DrawResult PrepareToDrawOnThread(
- LayerTreeHostImpl* host_impl,
- LayerTreeHostImpl::FrameData* frame_data,
- DrawResult draw_result);
- virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) {}
- virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) {}
- virtual void SwapBuffersCompleteOnThread(LayerTreeHostImpl* host_impl) {}
- virtual void NotifyReadyToActivateOnThread(LayerTreeHostImpl* host_impl) {}
- virtual void NotifyReadyToDrawOnThread(LayerTreeHostImpl* host_impl) {}
- virtual void NotifyAllTileTasksCompleted(LayerTreeHostImpl* host_impl) {}
- virtual void NotifyTileStateChangedOnThread(LayerTreeHostImpl* host_impl,
- const Tile* tile) {}
- virtual void AnimateLayers(LayerTreeHostImpl* host_impl,
- base::TimeTicks monotonic_time) {}
- virtual void UpdateAnimationState(LayerTreeHostImpl* host_impl,
- bool has_unfinished_animation) {}
- virtual void WillAnimateLayers(LayerTreeHostImpl* host_impl,
- base::TimeTicks monotonic_time) {}
- virtual void ApplyViewportDeltas(
- const gfx::Vector2dF& inner_delta,
- const gfx::Vector2dF& outer_delta,
- const gfx::Vector2dF& elastic_overscroll_delta,
- float scale,
- float top_controls_delta) {}
- virtual void BeginMainFrame(const BeginFrameArgs& args) {}
- virtual void WillBeginMainFrame() {}
- virtual void DidBeginMainFrame() {}
- virtual void UpdateLayerTreeHost() {}
- virtual void DidInitializeOutputSurface() {}
- virtual void DidFailToInitializeOutputSurface() {}
- virtual void DidAddAnimation() {}
- virtual void WillCommit() {}
- virtual void DidCommit() {}
- virtual void DidCommitAndDrawFrame() {}
- virtual void DidCompleteSwapBuffers() {}
- virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* host_impl,
- bool visible) {}
- virtual void ScheduleComposite() {}
- virtual void DidSetNeedsUpdateLayers() {}
- virtual void DidActivateSyncTree() {}
-
- // Hooks for SchedulerClient.
- virtual void ScheduledActionWillSendBeginMainFrame() {}
- virtual void ScheduledActionSendBeginMainFrame() {}
- virtual void ScheduledActionDrawAndSwapIfPossible() {}
- virtual void ScheduledActionCommit() {}
- virtual void ScheduledActionBeginOutputSurfaceCreation() {}
- virtual void ScheduledActionPrepareTiles() {}
- virtual void ScheduledActionInvalidateOutputSurface() {}
- virtual void SendBeginFramesToChildren(const BeginFrameArgs& args) {}
- virtual void SendBeginMainFrameNotExpectedSoon() {}
-
- // Hooks for ProxyImpl
- virtual void SetThrottleFrameProductionOnImpl(bool throttle) {}
- virtual void UpdateTopControlsStateOnImpl(TopControlsState constraints,
- TopControlsState current,
- bool animate) {}
- virtual void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) {}
- virtual void MainThreadHasStoppedFlingingOnImpl() {}
- virtual void SetInputThrottledUntilCommitOnImpl(bool is_throttled) {}
- virtual void SetDeferCommitsOnImpl(bool defer_commits) {}
- virtual void BeginMainFrameAbortedOnImpl(CommitEarlyOutReason reason) {}
- virtual void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {}
- virtual void SetNeedsCommitOnImpl() {}
- virtual void FinishAllRenderingOnImpl() {}
- virtual void SetVisibleOnImpl(bool visible) {}
- virtual void ReleaseOutputSurfaceOnImpl() {}
- virtual void FinishGLOnImpl() {}
- virtual void StartCommitOnImpl() {}
- virtual void InitializeImplOnImpl() {}
- virtual void WillCloseLayerTreeHostOnImpl() {}
-
- // Hooks for ProxyMain
- virtual void ReceivedDidCompleteSwapBuffers() {}
- virtual void ReceivedSetRendererCapabilitiesMainCopy(
- const RendererCapabilities& capabilities) {}
- virtual void ReceivedBeginMainFrameNotExpectedSoon() {}
- virtual void ReceivedDidCommitAndDrawFrame() {}
- virtual void ReceivedSetAnimationEvents() {}
- virtual void ReceivedDidLoseOutputSurface() {}
- virtual void ReceivedRequestNewOutputSurface() {}
- virtual void ReceivedDidInitializeOutputSurface(
- bool success,
- const RendererCapabilities& capabilities) {}
- virtual void ReceivedDidCompletePageScaleAnimation() {}
- virtual void ReceivedPostFrameTimingEventsOnMain() {}
- virtual void ReceivedBeginMainFrame() {}
-
- // Implementation of AnimationDelegate:
- void NotifyAnimationStarted(base::TimeTicks monotonic_time,
- Animation::TargetProperty target_property,
- int group) override {}
- void NotifyAnimationFinished(base::TimeTicks monotonic_time,
- Animation::TargetProperty target_property,
- int group) override {}
-
- virtual void RequestNewOutputSurface() = 0;
-};
-
class BeginTask;
class LayerTreeHostClientForTesting;
class TimeoutTask;
@@ -250,9 +129,10 @@ class LayerTreeTest : public testing::Test, public TestHooks {
virtual void BeginTest() = 0;
virtual void SetupTree();
+ // TODO(khushalsagar): Add mode for running remote channel tests.
virtual void RunTest(CompositorMode mode, bool delegating_renderer);
- bool HasImplThread() { return !!impl_thread_; }
+ bool HasImplThread() const { return !!impl_thread_; }
base::SingleThreadTaskRunner* ImplThreadTaskRunner() {
DCHECK(task_runner_provider());
base::SingleThreadTaskRunner* impl_thread_task_runner =
@@ -278,6 +158,12 @@ class LayerTreeTest : public testing::Test, public TestHooks {
FakeOutputSurface* output_surface() { return output_surface_; }
int LastCommittedSourceFrameNumber(LayerTreeHostImpl* impl) const;
+ // Use these only for ProxyMain tests in threaded mode.
+ // TODO(khushalsagar): Update these when adding support for remote channel
+ // tests.
+ ProxyMainForTest* GetProxyMainForTest() const;
+ ProxyImplForTest* GetProxyImplForTest() const;
+
void DestroyLayerTreeHost();
// By default, output surface recreation is synchronous.
diff --git a/cc/test/proxy_impl_for_test.cc b/cc/test/proxy_impl_for_test.cc
new file mode 100644
index 0000000..3cd542b
--- /dev/null
+++ b/cc/test/proxy_impl_for_test.cc
@@ -0,0 +1,163 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/proxy_impl_for_test.h"
+
+namespace cc {
+scoped_ptr<ProxyImpl> ProxyImplForTest::Create(
+ TestHooks* test_hooks,
+ ChannelImpl* channel_impl,
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+ return make_scoped_ptr(new ProxyImplForTest(
+ test_hooks, channel_impl, layer_tree_host, task_runner_provider,
+ std::move(external_begin_frame_source)));
+}
+
+bool ProxyImplForTest::HasCommitCompletionEvent() const {
+ return commit_completion_event_ != nullptr;
+}
+
+bool ProxyImplForTest::GetNextCommitWaitsForActivation() const {
+ return next_commit_waits_for_activation_;
+}
+
+ProxyImplForTest::ProxyImplForTest(
+ TestHooks* test_hooks,
+ ChannelImpl* channel_impl,
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source)
+ : ProxyImpl(channel_impl,
+ layer_tree_host,
+ task_runner_provider,
+ std::move(external_begin_frame_source)),
+ test_hooks_(test_hooks) {}
+
+void ProxyImplForTest::ScheduledActionSendBeginMainFrame(
+ const BeginFrameArgs& args) {
+ test_hooks_->ScheduledActionWillSendBeginMainFrame();
+ ProxyImpl::ScheduledActionSendBeginMainFrame(args);
+ test_hooks_->ScheduledActionSendBeginMainFrame();
+}
+
+DrawResult ProxyImplForTest::ScheduledActionDrawAndSwapIfPossible() {
+ DrawResult result = ProxyImpl::ScheduledActionDrawAndSwapIfPossible();
+ test_hooks_->ScheduledActionDrawAndSwapIfPossible();
+ return result;
+}
+
+void ProxyImplForTest::ScheduledActionCommit() {
+ ProxyImpl::ScheduledActionCommit();
+ test_hooks_->ScheduledActionCommit();
+}
+
+void ProxyImplForTest::ScheduledActionBeginOutputSurfaceCreation() {
+ ProxyImpl::ScheduledActionBeginOutputSurfaceCreation();
+ test_hooks_->ScheduledActionBeginOutputSurfaceCreation();
+}
+
+void ProxyImplForTest::ScheduledActionPrepareTiles() {
+ ProxyImpl::ScheduledActionPrepareTiles();
+ test_hooks_->ScheduledActionPrepareTiles();
+}
+
+void ProxyImplForTest::ScheduledActionInvalidateOutputSurface() {
+ ProxyImpl::ScheduledActionInvalidateOutputSurface();
+ test_hooks_->ScheduledActionInvalidateOutputSurface();
+}
+
+void ProxyImplForTest::SendBeginMainFrameNotExpectedSoon() {
+ ProxyImpl::SendBeginMainFrameNotExpectedSoon();
+ test_hooks_->SendBeginMainFrameNotExpectedSoon();
+}
+
+void ProxyImplForTest::DidActivateSyncTree() {
+ ProxyImpl::DidActivateSyncTree();
+ test_hooks_->DidActivateSyncTree();
+}
+
+void ProxyImplForTest::SetThrottleFrameProductionOnImpl(bool throttle) {
+ test_hooks_->SetThrottleFrameProductionOnImpl(throttle);
+ ProxyImpl::SetThrottleFrameProductionOnImpl(throttle);
+}
+
+void ProxyImplForTest::InitializeOutputSurfaceOnImpl(
+ OutputSurface* output_surface) {
+ test_hooks_->InitializeOutputSurfaceOnImpl(output_surface);
+ ProxyImpl::InitializeOutputSurfaceOnImpl(output_surface);
+}
+
+void ProxyImplForTest::MainThreadHasStoppedFlingingOnImpl() {
+ test_hooks_->MainThreadHasStoppedFlingingOnImpl();
+ ProxyImpl::MainThreadHasStoppedFlingingOnImpl();
+}
+
+void ProxyImplForTest::SetInputThrottledUntilCommitOnImpl(bool is_throttled) {
+ test_hooks_->SetInputThrottledUntilCommitOnImpl(is_throttled);
+ ProxyImpl::SetInputThrottledUntilCommitOnImpl(is_throttled);
+}
+
+void ProxyImplForTest::UpdateTopControlsStateOnImpl(
+ TopControlsState constraints,
+ TopControlsState current,
+ bool animate) {
+ test_hooks_->UpdateTopControlsStateOnImpl(constraints, current, animate);
+ ProxyImpl::UpdateTopControlsStateOnImpl(constraints, current, animate);
+}
+
+void ProxyImplForTest::SetDeferCommitsOnImpl(bool defer_commits) const {
+ test_hooks_->SetDeferCommitsOnImpl(defer_commits);
+ ProxyImpl::SetDeferCommitsOnImpl(defer_commits);
+}
+
+void ProxyImplForTest::BeginMainFrameAbortedOnImpl(
+ CommitEarlyOutReason reason,
+ base::TimeTicks main_thread_start_time) {
+ test_hooks_->BeginMainFrameAbortedOnImpl(reason);
+ ProxyImpl::BeginMainFrameAbortedOnImpl(reason, main_thread_start_time);
+}
+
+void ProxyImplForTest::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
+ test_hooks_->SetNeedsRedrawOnImpl(damage_rect);
+ ProxyImpl::SetNeedsRedrawOnImpl(damage_rect);
+}
+
+void ProxyImplForTest::SetNeedsCommitOnImpl() {
+ test_hooks_->SetNeedsCommitOnImpl();
+ ProxyImpl::SetNeedsCommitOnImpl();
+}
+
+void ProxyImplForTest::FinishAllRenderingOnImpl(CompletionEvent* completion) {
+ test_hooks_->FinishAllRenderingOnImpl();
+ ProxyImpl::FinishAllRenderingOnImpl(completion);
+}
+
+void ProxyImplForTest::SetVisibleOnImpl(bool visible) {
+ test_hooks_->SetVisibleOnImpl(visible);
+ ProxyImpl::SetVisibleOnImpl(visible);
+}
+
+void ProxyImplForTest::ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) {
+ test_hooks_->ReleaseOutputSurfaceOnImpl();
+ ProxyImpl::ReleaseOutputSurfaceOnImpl(completion);
+}
+
+void ProxyImplForTest::FinishGLOnImpl(CompletionEvent* completion) {
+ test_hooks_->FinishGLOnImpl();
+ ProxyImpl::FinishGLOnImpl(completion);
+}
+
+void ProxyImplForTest::StartCommitOnImpl(CompletionEvent* completion,
+ LayerTreeHost* layer_tree_host,
+ base::TimeTicks main_thread_start_time,
+ bool hold_commit_for_activation) {
+ test_hooks_->StartCommitOnImpl();
+ ProxyImpl::StartCommitOnImpl(completion, layer_tree_host,
+ main_thread_start_time,
+ hold_commit_for_activation);
+}
+
+} // namespace cc
diff --git a/cc/test/proxy_impl_for_test.h b/cc/test/proxy_impl_for_test.h
new file mode 100644
index 0000000..b81ece5
--- /dev/null
+++ b/cc/test/proxy_impl_for_test.h
@@ -0,0 +1,73 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TEST_PROXY_IMPL_FOR_TEST_H_
+#define CC_TEST_PROXY_IMPL_FOR_TEST_H_
+
+#include "base/macros.h"
+#include "cc/test/test_hooks.h"
+#include "cc/trees/proxy_impl.h"
+
+namespace cc {
+// Creates a ProxyImpl that notifies the supplied |test_hooks| of various
+// actions.
+class ProxyImplForTest : public ProxyImpl {
+ public:
+ static scoped_ptr<ProxyImpl> Create(
+ TestHooks* test_hooks,
+ ChannelImpl* channel_impl,
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+ using ProxyImpl::PostAnimationEventsToMainThreadOnImplThread;
+ using ProxyImpl::DidLoseOutputSurfaceOnImplThread;
+ using ProxyImpl::DidCompletePageScaleAnimationOnImplThread;
+ using ProxyImpl::SendBeginMainFrameNotExpectedSoon;
+
+ bool HasCommitCompletionEvent() const;
+ bool GetNextCommitWaitsForActivation() const;
+
+ ProxyImplForTest(TestHooks* test_hooks,
+ ChannelImpl* channel_impl,
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+ void ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) override;
+ DrawResult ScheduledActionDrawAndSwapIfPossible() override;
+ void ScheduledActionCommit() override;
+ void ScheduledActionBeginOutputSurfaceCreation() override;
+ void ScheduledActionPrepareTiles() override;
+ void ScheduledActionInvalidateOutputSurface() override;
+ void SendBeginMainFrameNotExpectedSoon() override;
+ void DidActivateSyncTree() override;
+ void SetThrottleFrameProductionOnImpl(bool throttle) override;
+ void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) override;
+ void MainThreadHasStoppedFlingingOnImpl() override;
+ void SetInputThrottledUntilCommitOnImpl(bool is_throttled) override;
+ void UpdateTopControlsStateOnImpl(TopControlsState constraints,
+ TopControlsState current,
+ bool animate) override;
+ void SetDeferCommitsOnImpl(bool defer_commits) const override;
+ void BeginMainFrameAbortedOnImpl(
+ CommitEarlyOutReason reason,
+ base::TimeTicks main_thread_start_time) override;
+ void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) override;
+ void SetNeedsCommitOnImpl() override;
+ void FinishAllRenderingOnImpl(CompletionEvent* completion) override;
+ void SetVisibleOnImpl(bool visible) override;
+ void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) override;
+ void FinishGLOnImpl(CompletionEvent* completion) override;
+ void StartCommitOnImpl(CompletionEvent* completion,
+ LayerTreeHost* layer_tree_host,
+ base::TimeTicks main_thread_start_time,
+ bool hold_commit_for_activation) override;
+
+ TestHooks* test_hooks_;
+};
+
+} // namespace cc
+
+#endif // CC_TEST_PROXY_IMPL_FOR_TEST_H_
diff --git a/cc/test/proxy_main_for_test.cc b/cc/test/proxy_main_for_test.cc
new file mode 100644
index 0000000..4588422
--- /dev/null
+++ b/cc/test/proxy_main_for_test.cc
@@ -0,0 +1,104 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/proxy_main_for_test.h"
+
+#include "cc/test/threaded_channel_for_test.h"
+
+namespace cc {
+
+scoped_ptr<ProxyMain> ProxyMainForTest::CreateThreaded(
+ TestHooks* test_hooks,
+ LayerTreeHost* host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+ scoped_ptr<ProxyMain> proxy_main(
+ new ProxyMainForTest(test_hooks, host, task_runner_provider,
+ std::move(external_begin_frame_source)));
+ proxy_main->SetChannel(ThreadedChannelForTest::Create(
+ test_hooks, proxy_main.get(), task_runner_provider));
+ return proxy_main;
+}
+
+ProxyMainForTest::~ProxyMainForTest() {}
+
+ProxyMainForTest::ProxyMainForTest(
+ TestHooks* test_hooks,
+ LayerTreeHost* host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source)
+ : ProxyMain(host,
+ task_runner_provider,
+ std::move(external_begin_frame_source)),
+ test_hooks_(test_hooks) {}
+
+void ProxyMainForTest::SetNeedsUpdateLayers() {
+ ProxyMain::SetNeedsUpdateLayers();
+ test_hooks_->DidSetNeedsUpdateLayers();
+}
+
+void ProxyMainForTest::DidCompleteSwapBuffers() {
+ test_hooks_->ReceivedDidCompleteSwapBuffers();
+ ProxyMain::DidCompleteSwapBuffers();
+}
+
+void ProxyMainForTest::SetRendererCapabilities(
+ const RendererCapabilities& capabilities) {
+ test_hooks_->ReceivedSetRendererCapabilitiesMainCopy(capabilities);
+ ProxyMain::SetRendererCapabilities(capabilities);
+}
+
+void ProxyMainForTest::BeginMainFrameNotExpectedSoon() {
+ test_hooks_->ReceivedBeginMainFrameNotExpectedSoon();
+ ProxyMain::BeginMainFrameNotExpectedSoon();
+}
+
+void ProxyMainForTest::DidCommitAndDrawFrame() {
+ test_hooks_->ReceivedDidCommitAndDrawFrame();
+ ProxyMain::DidCommitAndDrawFrame();
+}
+
+void ProxyMainForTest::SetAnimationEvents(
+ scoped_ptr<AnimationEventsVector> events) {
+ test_hooks_->ReceivedSetAnimationEvents();
+ ProxyMain::SetAnimationEvents(std::move(events));
+}
+
+void ProxyMainForTest::DidLoseOutputSurface() {
+ test_hooks_->ReceivedDidLoseOutputSurface();
+ ProxyMain::DidLoseOutputSurface();
+}
+
+void ProxyMainForTest::RequestNewOutputSurface() {
+ test_hooks_->ReceivedRequestNewOutputSurface();
+ ProxyMain::RequestNewOutputSurface();
+}
+
+void ProxyMainForTest::DidInitializeOutputSurface(
+ bool success,
+ const RendererCapabilities& capabilities) {
+ test_hooks_->ReceivedDidInitializeOutputSurface(success, capabilities);
+ ProxyMain::DidInitializeOutputSurface(success, capabilities);
+}
+
+void ProxyMainForTest::DidCompletePageScaleAnimation() {
+ test_hooks_->ReceivedDidCompletePageScaleAnimation();
+ ProxyMain::DidCompletePageScaleAnimation();
+}
+
+void ProxyMainForTest::PostFrameTimingEventsOnMain(
+ scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
+ scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
+ test_hooks_->ReceivedPostFrameTimingEventsOnMain();
+ ProxyMain::PostFrameTimingEventsOnMain(std::move(composite_events),
+ std::move(main_frame_events));
+}
+
+void ProxyMainForTest::BeginMainFrame(
+ scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
+ test_hooks_->ReceivedBeginMainFrame();
+ ProxyMain::BeginMainFrame(std::move(begin_main_frame_state));
+}
+
+} // namespace cc
diff --git a/cc/test/proxy_main_for_test.h b/cc/test/proxy_main_for_test.h
new file mode 100644
index 0000000..1669cc5
--- /dev/null
+++ b/cc/test/proxy_main_for_test.h
@@ -0,0 +1,56 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TEST_PROXY_MAIN_FOR_TEST_H_
+#define CC_TEST_PROXY_MAIN_FOR_TEST_H_
+
+#include "base/macros.h"
+#include "cc/test/test_hooks.h"
+#include "cc/trees/proxy_main.h"
+
+namespace cc {
+
+// Creates a ProxyMain that notifies the supplied |test_hooks| of various
+// actions.
+class ProxyMainForTest : public ProxyMain {
+ public:
+ static scoped_ptr<ProxyMain> CreateThreaded(
+ TestHooks* test_hooks,
+ LayerTreeHost* host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+ ~ProxyMainForTest() override;
+
+ ProxyMainForTest(TestHooks* test_hooks,
+ LayerTreeHost* host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+ void SetNeedsUpdateLayers() override;
+ void DidCompleteSwapBuffers() override;
+ void SetRendererCapabilities(
+ const RendererCapabilities& capabilities) override;
+ void BeginMainFrameNotExpectedSoon() override;
+ void DidCommitAndDrawFrame() override;
+ void SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) override;
+ void DidLoseOutputSurface() override;
+ void RequestNewOutputSurface() override;
+ void DidInitializeOutputSurface(
+ bool success,
+ const RendererCapabilities& capabilities) override;
+ void DidCompletePageScaleAnimation() override;
+ void PostFrameTimingEventsOnMain(
+ scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
+ scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
+ override;
+ void BeginMainFrame(
+ scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) override;
+
+ TestHooks* test_hooks_;
+};
+
+} // namespace cc
+
+#endif // CC_TEST_PROXY_MAIN_FOR_TEST_H_
diff --git a/cc/test/test_hooks.cc b/cc/test/test_hooks.cc
new file mode 100644
index 0000000..5c913ac
--- /dev/null
+++ b/cc/test/test_hooks.cc
@@ -0,0 +1,28 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/test_hooks.h"
+
+namespace cc {
+
+TestHooks::TestHooks() {}
+
+TestHooks::~TestHooks() {}
+
+DrawResult TestHooks::PrepareToDrawOnThread(
+ LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ DrawResult draw_result) {
+ return draw_result;
+}
+
+void TestHooks::CreateResourceAndTileTaskWorkerPool(
+ LayerTreeHostImpl* host_impl,
+ scoped_ptr<TileTaskWorkerPool>* tile_task_worker_pool,
+ scoped_ptr<ResourcePool>* resource_pool) {
+ host_impl->LayerTreeHostImpl::CreateResourceAndTileTaskWorkerPool(
+ tile_task_worker_pool, resource_pool);
+}
+
+} // namespace cc
diff --git a/cc/test/test_hooks.h b/cc/test/test_hooks.h
new file mode 100644
index 0000000..fd45cbc
--- /dev/null
+++ b/cc/test/test_hooks.h
@@ -0,0 +1,139 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TEST_TEST_HOOKS_H_
+#define CC_TEST_TEST_HOOKS_H_
+
+#include "base/macros.h"
+#include "cc/animation/animation_delegate.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_host_impl.h"
+
+namespace cc {
+
+// Used by test stubs to notify the test when something interesting happens.
+class TestHooks : public AnimationDelegate {
+ public:
+ TestHooks();
+ ~TestHooks() override;
+
+ void ReadSettings(const LayerTreeSettings& settings);
+
+ virtual void CreateResourceAndTileTaskWorkerPool(
+ LayerTreeHostImpl* host_impl,
+ scoped_ptr<TileTaskWorkerPool>* tile_task_worker_pool,
+ scoped_ptr<ResourcePool>* resource_pool);
+ virtual void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
+ const BeginFrameArgs& args) {}
+ virtual void DidFinishImplFrameOnThread(LayerTreeHostImpl* host_impl) {}
+ virtual void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl,
+ CommitEarlyOutReason reason) {}
+ virtual void WillPrepareTiles(LayerTreeHostImpl* host_impl) {}
+ virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) {}
+ virtual void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) {}
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) {}
+ virtual void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) {}
+ virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) {}
+ virtual void InitializedRendererOnThread(LayerTreeHostImpl* host_impl,
+ bool success) {}
+ virtual DrawResult PrepareToDrawOnThread(
+ LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ DrawResult draw_result);
+ virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) {}
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) {}
+ virtual void SwapBuffersCompleteOnThread(LayerTreeHostImpl* host_impl) {}
+ virtual void NotifyReadyToActivateOnThread(LayerTreeHostImpl* host_impl) {}
+ virtual void NotifyReadyToDrawOnThread(LayerTreeHostImpl* host_impl) {}
+ virtual void NotifyAllTileTasksCompleted(LayerTreeHostImpl* host_impl) {}
+ virtual void NotifyTileStateChangedOnThread(LayerTreeHostImpl* host_impl,
+ const Tile* tile) {}
+ virtual void AnimateLayers(LayerTreeHostImpl* host_impl,
+ base::TimeTicks monotonic_time) {}
+ virtual void UpdateAnimationState(LayerTreeHostImpl* host_impl,
+ bool has_unfinished_animation) {}
+ virtual void WillAnimateLayers(LayerTreeHostImpl* host_impl,
+ base::TimeTicks monotonic_time) {}
+ virtual void ApplyViewportDeltas(
+ const gfx::Vector2dF& inner_delta,
+ const gfx::Vector2dF& outer_delta,
+ const gfx::Vector2dF& elastic_overscroll_delta,
+ float scale,
+ float top_controls_delta) {}
+ virtual void BeginMainFrame(const BeginFrameArgs& args) {}
+ virtual void WillBeginMainFrame() {}
+ virtual void DidBeginMainFrame() {}
+ virtual void UpdateLayerTreeHost() {}
+ virtual void DidInitializeOutputSurface() {}
+ virtual void DidFailToInitializeOutputSurface() {}
+ virtual void DidAddAnimation() {}
+ virtual void WillCommit() {}
+ virtual void DidCommit() {}
+ virtual void DidCommitAndDrawFrame() {}
+ virtual void DidCompleteSwapBuffers() {}
+ virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* host_impl,
+ bool visible) {}
+ virtual void ScheduleComposite() {}
+ virtual void DidSetNeedsUpdateLayers() {}
+ virtual void DidActivateSyncTree() {}
+
+ // Hooks for SchedulerClient.
+ virtual void ScheduledActionWillSendBeginMainFrame() {}
+ virtual void ScheduledActionSendBeginMainFrame() {}
+ virtual void ScheduledActionDrawAndSwapIfPossible() {}
+ virtual void ScheduledActionCommit() {}
+ virtual void ScheduledActionBeginOutputSurfaceCreation() {}
+ virtual void ScheduledActionPrepareTiles() {}
+ virtual void ScheduledActionInvalidateOutputSurface() {}
+ virtual void SendBeginFramesToChildren(const BeginFrameArgs& args) {}
+ virtual void SendBeginMainFrameNotExpectedSoon() {}
+
+ // Hooks for ProxyImpl
+ virtual void SetThrottleFrameProductionOnImpl(bool throttle) {}
+ virtual void UpdateTopControlsStateOnImpl(TopControlsState constraints,
+ TopControlsState current,
+ bool animate) {}
+ virtual void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) {}
+ virtual void MainThreadHasStoppedFlingingOnImpl() {}
+ virtual void SetInputThrottledUntilCommitOnImpl(bool is_throttled) {}
+ virtual void SetDeferCommitsOnImpl(bool defer_commits) {}
+ virtual void BeginMainFrameAbortedOnImpl(CommitEarlyOutReason reason) {}
+ virtual void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {}
+ virtual void SetNeedsCommitOnImpl() {}
+ virtual void FinishAllRenderingOnImpl() {}
+ virtual void SetVisibleOnImpl(bool visible) {}
+ virtual void ReleaseOutputSurfaceOnImpl() {}
+ virtual void FinishGLOnImpl() {}
+ virtual void StartCommitOnImpl() {}
+
+ // Hooks for ProxyMain
+ virtual void ReceivedDidCompleteSwapBuffers() {}
+ virtual void ReceivedSetRendererCapabilitiesMainCopy(
+ const RendererCapabilities& capabilities) {}
+ virtual void ReceivedBeginMainFrameNotExpectedSoon() {}
+ virtual void ReceivedDidCommitAndDrawFrame() {}
+ virtual void ReceivedSetAnimationEvents() {}
+ virtual void ReceivedDidLoseOutputSurface() {}
+ virtual void ReceivedRequestNewOutputSurface() {}
+ virtual void ReceivedDidInitializeOutputSurface(
+ bool success,
+ const RendererCapabilities& capabilities) {}
+ virtual void ReceivedDidCompletePageScaleAnimation() {}
+ virtual void ReceivedPostFrameTimingEventsOnMain() {}
+ virtual void ReceivedBeginMainFrame() {}
+
+ // Implementation of AnimationDelegate:
+ void NotifyAnimationStarted(base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property,
+ int group) override {}
+ void NotifyAnimationFinished(base::TimeTicks monotonic_time,
+ Animation::TargetProperty target_property,
+ int group) override {}
+
+ virtual void RequestNewOutputSurface() = 0;
+};
+
+} // namespace cc
+
+#endif // CC_TEST_TEST_HOOKS_H_
diff --git a/cc/test/threaded_channel_for_test.cc b/cc/test/threaded_channel_for_test.cc
new file mode 100644
index 0000000..35489bd
--- /dev/null
+++ b/cc/test/threaded_channel_for_test.cc
@@ -0,0 +1,36 @@
+// Copyright 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/threaded_channel_for_test.h"
+
+#include "cc/test/proxy_impl_for_test.h"
+
+namespace cc {
+
+scoped_ptr<ThreadedChannel> ThreadedChannelForTest::Create(
+ TestHooks* test_hooks,
+ ProxyMain* proxy_main,
+ TaskRunnerProvider* task_runner_provider) {
+ return make_scoped_ptr(
+ new ThreadedChannelForTest(test_hooks, proxy_main, task_runner_provider));
+}
+
+ThreadedChannelForTest::ThreadedChannelForTest(
+ TestHooks* test_hooks,
+ ProxyMain* proxy_main,
+ TaskRunnerProvider* task_runner_provider)
+ : ThreadedChannel(proxy_main, task_runner_provider),
+ test_hooks_(test_hooks) {}
+
+scoped_ptr<ProxyImpl> ThreadedChannelForTest::CreateProxyImpl(
+ ChannelImpl* channel_impl,
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+ return ProxyImplForTest::Create(test_hooks_, channel_impl, layer_tree_host,
+ task_runner_provider,
+ std::move(external_begin_frame_source));
+}
+
+} // namespace cc
diff --git a/cc/test/threaded_channel_for_test.h b/cc/test/threaded_channel_for_test.h
new file mode 100644
index 0000000..bd74790
--- /dev/null
+++ b/cc/test/threaded_channel_for_test.h
@@ -0,0 +1,38 @@
+// Copyright 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TEST_THREADED_CHANNEL_FOR_TEST_H_
+#define CC_TEST_THREADED_CHANNEL_FOR_TEST_H_
+
+#include "base/macros.h"
+#include "cc/test/test_hooks.h"
+#include "cc/trees/threaded_channel.h"
+
+namespace cc {
+
+// ThreadedChannel that notifies |test_hooks| of internal actions by ProxyImpl.
+class ThreadedChannelForTest : public ThreadedChannel {
+ public:
+ static scoped_ptr<ThreadedChannel> Create(
+ TestHooks* test_hooks,
+ ProxyMain* proxy_main,
+ TaskRunnerProvider* task_runner_provider);
+
+ private:
+ ThreadedChannelForTest(TestHooks* test_hooks,
+ ProxyMain* proxy_main,
+ TaskRunnerProvider* task_runner_provider);
+
+ scoped_ptr<ProxyImpl> CreateProxyImpl(
+ ChannelImpl* channel_impl,
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source) override;
+
+ TestHooks* test_hooks_;
+};
+
+} // namespace cc
+
+#endif // CC_TEST_THREADED_CHANNEL_FOR_TEST_H_
diff --git a/cc/trees/channel_main.h b/cc/trees/channel_main.h
index 8f8c4ee..39861e0 100644
--- a/cc/trees/channel_main.h
+++ b/cc/trees/channel_main.h
@@ -9,10 +9,12 @@
#include "cc/base/completion_event.h"
#include "cc/input/top_controls_state.h"
#include "cc/output/output_surface.h"
+#include "cc/scheduler/begin_frame_source.h"
#include "cc/scheduler/commit_earlyout_reason.h"
#include "cc/trees/proxy_common.h"
namespace cc {
+
// ChannelMain and ChannelImpl provide an abstract communication layer for
// the main and impl side of the compositor.
//
@@ -25,7 +27,9 @@ namespace cc {
class CC_EXPORT ChannelMain {
public:
- // Interface for commands sent to the ProxyImpl
+ virtual ~ChannelMain() {}
+
+ // Interface for commands sent to ProxyImpl
virtual void SetThrottleFrameProductionOnImpl(bool throttle) = 0;
virtual void UpdateTopControlsStateOnImpl(TopControlsState constraints,
TopControlsState current,
@@ -37,7 +41,6 @@ class CC_EXPORT ChannelMain {
virtual void FinishAllRenderingOnImpl(CompletionEvent* completion) = 0;
virtual void SetVisibleOnImpl(bool visible) = 0;
virtual void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) = 0;
- virtual void FinishGLOnImpl(CompletionEvent* completion) = 0;
virtual void MainFrameWillHappenOnImplForTesting(
CompletionEvent* completion,
bool* main_frame_will_happen) = 0;
@@ -50,11 +53,14 @@ class CC_EXPORT ChannelMain {
LayerTreeHost* layer_tree_host,
base::TimeTicks main_thread_start_time,
bool hold_commit_for_activation) = 0;
- virtual void InitializeImplOnImpl(CompletionEvent* completion,
- LayerTreeHost* layer_tree_host) = 0;
- virtual void LayerTreeHostClosedOnImpl(CompletionEvent* completion) = 0;
- virtual ~ChannelMain() {}
+ // Must be called before using the channel.
+ virtual void SynchronouslyInitializeImpl(
+ LayerTreeHost* layer_tree_host,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source) = 0;
+
+ // Must be called before deleting the channel.
+ virtual void SynchronouslyCloseImpl() = 0;
};
} // namespace cc
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index b5f0231..6eb60f6 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -42,8 +42,8 @@
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/proxy_main.h"
#include "cc/trees/single_thread_proxy.h"
-#include "cc/trees/thread_proxy.h"
#include "cc/trees/tree_synchronizer.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
@@ -143,8 +143,10 @@ void LayerTreeHost::InitializeThreaded(
scoped_ptr<BeginFrameSource> external_begin_frame_source) {
task_runner_provider_ =
TaskRunnerProvider::Create(main_task_runner, impl_task_runner);
- InitializeProxy(ThreadProxy::Create(this, task_runner_provider_.get(),
- std::move(external_begin_frame_source)));
+ scoped_ptr<ProxyMain> proxy_main =
+ ProxyMain::CreateThreaded(this, task_runner_provider_.get(),
+ std::move(external_begin_frame_source));
+ InitializeProxy(std::move(proxy_main));
}
void LayerTreeHost::InitializeSingleThreaded(
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index f97d3d2..fdcc26d 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -49,7 +49,6 @@
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/single_thread_proxy.h"
-#include "cc/trees/thread_proxy.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "skia/ext/refptr.h"
#include "testing/gmock/include/gmock/gmock.h"
diff --git a/cc/trees/layer_tree_host_unittest_proxy.cc b/cc/trees/layer_tree_host_unittest_proxy.cc
index 293c864..e00b085 100644
--- a/cc/trees/layer_tree_host_unittest_proxy.cc
+++ b/cc/trees/layer_tree_host_unittest_proxy.cc
@@ -7,15 +7,16 @@
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/fake_picture_layer.h"
#include "cc/test/layer_tree_test.h"
-#include "cc/trees/thread_proxy.h"
+#include "cc/trees/proxy_impl.h"
+#include "cc/trees/proxy_main.h"
-#define THREAD_PROXY_TEST_F(TEST_FIXTURE_NAME) \
+#define PROXY_MAIN_THREADED_TEST_F(TEST_FIXTURE_NAME) \
TEST_F(TEST_FIXTURE_NAME, MultiThread) { Run(true); }
-// Do common tests for single thread proxy and thread proxy.
+// Do common tests for single thread proxy and proxy main in threaded mode.
// TODO(simonhong): Add SINGLE_THREAD_PROXY_TEST_F
#define PROXY_TEST_SCHEDULED_ACTION(TEST_FIXTURE_NAME) \
- THREAD_PROXY_TEST_F(TEST_FIXTURE_NAME);
+ PROXY_MAIN_THREADED_TEST_F(TEST_FIXTURE_NAME);
namespace cc {
@@ -73,12 +74,12 @@ class ProxyTestScheduledActionsBasic : public ProxyTest {
PROXY_TEST_SCHEDULED_ACTION(ProxyTestScheduledActionsBasic);
-class ThreadProxyTest : public ProxyTest {
+class ProxyMainThreaded : public ProxyTest {
protected:
- ThreadProxyTest()
+ ProxyMainThreaded()
: update_check_layer_(
FakePictureLayer::Create(layer_settings(), &client_)) {}
- ~ThreadProxyTest() override {}
+ ~ProxyMainThreaded() override {}
void SetupTree() override {
layer_tree_host()->SetRootLayer(update_check_layer_);
@@ -86,83 +87,69 @@ class ThreadProxyTest : public ProxyTest {
client_.set_bounds(update_check_layer_->bounds());
}
- const ThreadProxy::MainThreadOnly& ThreadProxyMainOnly() const {
- DCHECK(task_runner_provider());
- DCHECK(task_runner_provider()->HasImplThread());
- DCHECK(proxy());
- return static_cast<const ThreadProxy*>(proxy())->main();
- }
-
- const ThreadProxy::CompositorThreadOnly& ThreadProxyImplOnly() const {
- DCHECK(task_runner_provider());
- DCHECK(task_runner_provider()->HasImplThread());
- DCHECK(proxy());
- return static_cast<const ThreadProxy*>(proxy())->impl();
- }
-
protected:
FakeContentLayerClient client_;
scoped_refptr<FakePictureLayer> update_check_layer_;
private:
- DISALLOW_COPY_AND_ASSIGN(ThreadProxyTest);
+ DISALLOW_COPY_AND_ASSIGN(ProxyMainThreaded);
};
-class ThreadProxyTestSetNeedsCommit : public ThreadProxyTest {
+class ProxyMainThreadedSetNeedsCommit : public ProxyMainThreaded {
protected:
- ThreadProxyTestSetNeedsCommit() {}
- ~ThreadProxyTestSetNeedsCommit() override {}
+ ProxyMainThreadedSetNeedsCommit() {}
+ ~ProxyMainThreadedSetNeedsCommit() override {}
void BeginTest() override {
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
proxy()->SetNeedsCommit();
- EXPECT_EQ(ThreadProxy::COMMIT_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ProxyMain::COMMIT_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
}
void DidBeginMainFrame() override {
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().current_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->current_pipeline_stage());
}
void DidCommit() override {
EXPECT_EQ(1, update_check_layer_->update_count());
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().current_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->current_pipeline_stage());
EndTest();
}
private:
- DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsCommit);
+ DISALLOW_COPY_AND_ASSIGN(ProxyMainThreadedSetNeedsCommit);
};
-THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsCommit);
+PROXY_MAIN_THREADED_TEST_F(ProxyMainThreadedSetNeedsCommit);
-class ThreadProxyTestSetNeedsAnimate : public ThreadProxyTest {
+class ProxyMainThreadedSetNeedsAnimate : public ProxyMainThreaded {
protected:
- ThreadProxyTestSetNeedsAnimate() {}
- ~ThreadProxyTestSetNeedsAnimate() override {}
+ ProxyMainThreadedSetNeedsAnimate() {}
+ ~ProxyMainThreadedSetNeedsAnimate() override {}
void BeginTest() override {
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
proxy()->SetNeedsAnimate();
- EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ProxyMain::ANIMATE_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
}
void DidBeginMainFrame() override {
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().current_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->current_pipeline_stage());
}
void DidCommit() override {
@@ -171,31 +158,31 @@ class ThreadProxyTestSetNeedsAnimate : public ThreadProxyTest {
}
private:
- DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsAnimate);
+ DISALLOW_COPY_AND_ASSIGN(ProxyMainThreadedSetNeedsAnimate);
};
-THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsAnimate);
+PROXY_MAIN_THREADED_TEST_F(ProxyMainThreadedSetNeedsAnimate);
-class ThreadProxyTestSetNeedsUpdateLayers : public ThreadProxyTest {
+class ProxyMainThreadedSetNeedsUpdateLayers : public ProxyMainThreaded {
protected:
- ThreadProxyTestSetNeedsUpdateLayers() {}
- ~ThreadProxyTestSetNeedsUpdateLayers() override {}
+ ProxyMainThreadedSetNeedsUpdateLayers() {}
+ ~ProxyMainThreadedSetNeedsUpdateLayers() override {}
void BeginTest() override {
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
proxy()->SetNeedsUpdateLayers();
- EXPECT_EQ(ThreadProxy::UPDATE_LAYERS_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
+ EXPECT_EQ(ProxyMain::UPDATE_LAYERS_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
}
void DidBeginMainFrame() override {
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().current_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->current_pipeline_stage());
}
void DidCommit() override {
@@ -204,40 +191,40 @@ class ThreadProxyTestSetNeedsUpdateLayers : public ThreadProxyTest {
}
private:
- DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsUpdateLayers);
+ DISALLOW_COPY_AND_ASSIGN(ProxyMainThreadedSetNeedsUpdateLayers);
};
-THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsUpdateLayers);
+PROXY_MAIN_THREADED_TEST_F(ProxyMainThreadedSetNeedsUpdateLayers);
-class ThreadProxyTestSetNeedsUpdateLayersWhileAnimating
- : public ThreadProxyTest {
+class ProxyMainThreadedSetNeedsUpdateLayersWhileAnimating
+ : public ProxyMainThreaded {
protected:
- ThreadProxyTestSetNeedsUpdateLayersWhileAnimating() {}
- ~ThreadProxyTestSetNeedsUpdateLayersWhileAnimating() override {}
+ ProxyMainThreadedSetNeedsUpdateLayersWhileAnimating() {}
+ ~ProxyMainThreadedSetNeedsUpdateLayersWhileAnimating() override {}
void BeginTest() override { proxy()->SetNeedsAnimate(); }
void WillBeginMainFrame() override {
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
- EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
- ThreadProxyMainOnly().current_pipeline_stage);
- EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
- ThreadProxyMainOnly().final_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
+ EXPECT_EQ(ProxyMain::ANIMATE_PIPELINE_STAGE,
+ GetProxyMainForTest()->current_pipeline_stage());
+ EXPECT_EQ(ProxyMain::ANIMATE_PIPELINE_STAGE,
+ GetProxyMainForTest()->final_pipeline_stage());
proxy()->SetNeedsUpdateLayers();
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
- EXPECT_EQ(ThreadProxy::UPDATE_LAYERS_PIPELINE_STAGE,
- ThreadProxyMainOnly().final_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
+ EXPECT_EQ(ProxyMain::UPDATE_LAYERS_PIPELINE_STAGE,
+ GetProxyMainForTest()->final_pipeline_stage());
}
void DidBeginMainFrame() override {
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().current_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->current_pipeline_stage());
}
void DidCommit() override {
@@ -246,39 +233,39 @@ class ThreadProxyTestSetNeedsUpdateLayersWhileAnimating
}
private:
- DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsUpdateLayersWhileAnimating);
+ DISALLOW_COPY_AND_ASSIGN(ProxyMainThreadedSetNeedsUpdateLayersWhileAnimating);
};
-THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsUpdateLayersWhileAnimating);
+PROXY_MAIN_THREADED_TEST_F(ProxyMainThreadedSetNeedsUpdateLayersWhileAnimating);
-class ThreadProxyTestSetNeedsCommitWhileAnimating : public ThreadProxyTest {
+class ProxyMainThreadedSetNeedsCommitWhileAnimating : public ProxyMainThreaded {
protected:
- ThreadProxyTestSetNeedsCommitWhileAnimating() {}
- ~ThreadProxyTestSetNeedsCommitWhileAnimating() override {}
+ ProxyMainThreadedSetNeedsCommitWhileAnimating() {}
+ ~ProxyMainThreadedSetNeedsCommitWhileAnimating() override {}
void BeginTest() override { proxy()->SetNeedsAnimate(); }
void WillBeginMainFrame() override {
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
- EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
- ThreadProxyMainOnly().current_pipeline_stage);
- EXPECT_EQ(ThreadProxy::ANIMATE_PIPELINE_STAGE,
- ThreadProxyMainOnly().final_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
+ EXPECT_EQ(ProxyMain::ANIMATE_PIPELINE_STAGE,
+ GetProxyMainForTest()->current_pipeline_stage());
+ EXPECT_EQ(ProxyMain::ANIMATE_PIPELINE_STAGE,
+ GetProxyMainForTest()->final_pipeline_stage());
proxy()->SetNeedsCommit();
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
- EXPECT_EQ(ThreadProxy::COMMIT_PIPELINE_STAGE,
- ThreadProxyMainOnly().final_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
+ EXPECT_EQ(ProxyMain::COMMIT_PIPELINE_STAGE,
+ GetProxyMainForTest()->final_pipeline_stage());
}
void DidBeginMainFrame() override {
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().max_requested_pipeline_stage);
- EXPECT_EQ(ThreadProxy::NO_PIPELINE_STAGE,
- ThreadProxyMainOnly().current_pipeline_stage);
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->max_requested_pipeline_stage());
+ EXPECT_EQ(ProxyMain::NO_PIPELINE_STAGE,
+ GetProxyMainForTest()->current_pipeline_stage());
}
void DidCommit() override {
@@ -287,15 +274,15 @@ class ThreadProxyTestSetNeedsCommitWhileAnimating : public ThreadProxyTest {
}
private:
- DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestSetNeedsCommitWhileAnimating);
+ DISALLOW_COPY_AND_ASSIGN(ProxyMainThreadedSetNeedsCommitWhileAnimating);
};
-THREAD_PROXY_TEST_F(ThreadProxyTestSetNeedsCommitWhileAnimating);
+PROXY_MAIN_THREADED_TEST_F(ProxyMainThreadedSetNeedsCommitWhileAnimating);
-class ThreadProxyTestCommitWaitsForActivation : public ThreadProxyTest {
+class ProxyMainThreadedCommitWaitsForActivation : public ProxyMainThreaded {
protected:
- ThreadProxyTestCommitWaitsForActivation() : commits_completed_(0) {}
- ~ThreadProxyTestCommitWaitsForActivation() override {}
+ ProxyMainThreadedCommitWaitsForActivation() : commits_completed_(0) {}
+ ~ProxyMainThreadedCommitWaitsForActivation() override {}
void BeginTest() override { proxy()->SetNeedsCommit(); }
@@ -304,25 +291,25 @@ class ThreadProxyTestCommitWaitsForActivation : public ThreadProxyTest {
case 0:
// The first commit does not wait for activation. Verify that the
// completion event is cleared.
- EXPECT_FALSE(ThreadProxyImplOnly().commit_completion_event);
- EXPECT_FALSE(ThreadProxyImplOnly().next_commit_waits_for_activation);
+ EXPECT_FALSE(GetProxyImplForTest()->HasCommitCompletionEvent());
+ EXPECT_FALSE(GetProxyImplForTest()->GetNextCommitWaitsForActivation());
break;
case 1:
// The second commit should be held until activation.
- EXPECT_TRUE(ThreadProxyImplOnly().commit_completion_event);
- EXPECT_TRUE(ThreadProxyImplOnly().next_commit_waits_for_activation);
+ EXPECT_TRUE(GetProxyImplForTest()->HasCommitCompletionEvent());
+ EXPECT_TRUE(GetProxyImplForTest()->GetNextCommitWaitsForActivation());
break;
case 2:
// The third commit should not wait for activation.
- EXPECT_FALSE(ThreadProxyImplOnly().commit_completion_event);
- EXPECT_FALSE(ThreadProxyImplOnly().next_commit_waits_for_activation);
+ EXPECT_FALSE(GetProxyImplForTest()->HasCommitCompletionEvent());
+ EXPECT_FALSE(GetProxyImplForTest()->GetNextCommitWaitsForActivation());
}
}
void DidActivateSyncTree() override {
// The next_commit_waits_for_activation should have been cleared after the
// sync tree is activated.
- EXPECT_FALSE(ThreadProxyImplOnly().next_commit_waits_for_activation);
+ EXPECT_FALSE(GetProxyImplForTest()->GetNextCommitWaitsForActivation());
}
void DidCommit() override {
@@ -349,9 +336,9 @@ class ThreadProxyTestCommitWaitsForActivation : public ThreadProxyTest {
private:
int commits_completed_;
- DISALLOW_COPY_AND_ASSIGN(ThreadProxyTestCommitWaitsForActivation);
+ DISALLOW_COPY_AND_ASSIGN(ProxyMainThreadedCommitWaitsForActivation);
};
-THREAD_PROXY_TEST_F(ThreadProxyTestCommitWaitsForActivation);
+PROXY_MAIN_THREADED_TEST_F(ProxyMainThreadedCommitWaitsForActivation);
} // namespace cc
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
new file mode 100644
index 0000000..810e73e
--- /dev/null
+++ b/cc/trees/proxy_impl.cc
@@ -0,0 +1,684 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/trees/proxy_impl.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/auto_reset.h"
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_argument.h"
+#include "base/trace_event/trace_event_synthetic_delay.h"
+#include "cc/debug/benchmark_instrumentation.h"
+#include "cc/debug/devtools_instrumentation.h"
+#include "cc/input/top_controls_manager.h"
+#include "cc/output/context_provider.h"
+#include "cc/output/output_surface.h"
+#include "cc/scheduler/compositor_timing_history.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/task_runner_provider.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+
+namespace cc {
+
+namespace {
+
+// Measured in seconds.
+const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
+
+unsigned int nextBeginFrameId = 0;
+
+} // namespace
+
+scoped_ptr<ProxyImpl> ProxyImpl::Create(
+ ChannelImpl* channel_impl,
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+ return make_scoped_ptr(new ProxyImpl(channel_impl, layer_tree_host,
+ task_runner_provider,
+ std::move(external_begin_frame_source)));
+}
+
+ProxyImpl::ProxyImpl(ChannelImpl* channel_impl,
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source)
+ : layer_tree_host_id_(layer_tree_host->id()),
+ next_commit_waits_for_activation_(false),
+ commit_completion_event_(nullptr),
+ next_frame_is_newly_committed_frame_(false),
+ inside_draw_(false),
+ input_throttled_until_commit_(false),
+ task_runner_provider_(task_runner_provider),
+ smoothness_priority_expiration_notifier_(
+ task_runner_provider->ImplThreadTaskRunner(),
+ base::Bind(&ProxyImpl::RenewTreePriority, base::Unretained(this)),
+ base::TimeDelta::FromSeconds(
+ kSmoothnessTakesPriorityExpirationDelay)),
+ external_begin_frame_source_(std::move(external_begin_frame_source)),
+ rendering_stats_instrumentation_(
+ layer_tree_host->rendering_stats_instrumentation()),
+ channel_impl_(channel_impl) {
+ TRACE_EVENT0("cc", "ProxyImpl::ProxyImpl");
+ DCHECK(IsImplThread());
+ DCHECK(IsMainThreadBlocked());
+
+ layer_tree_host_impl_ = layer_tree_host->CreateLayerTreeHostImpl(this);
+
+ SchedulerSettings scheduler_settings(
+ layer_tree_host->settings().ToSchedulerSettings());
+
+ scoped_ptr<CompositorTimingHistory> compositor_timing_history(
+ new CompositorTimingHistory(CompositorTimingHistory::RENDERER_UMA,
+ rendering_stats_instrumentation_));
+
+ scheduler_ = Scheduler::Create(this, scheduler_settings, layer_tree_host_id_,
+ task_runner_provider_->ImplThreadTaskRunner(),
+ external_begin_frame_source_.get(),
+ std::move(compositor_timing_history));
+
+ DCHECK_EQ(scheduler_->visible(), layer_tree_host_impl_->visible());
+}
+
+ProxyImpl::BlockedMainCommitOnly::BlockedMainCommitOnly()
+ : layer_tree_host(nullptr) {}
+
+ProxyImpl::BlockedMainCommitOnly::~BlockedMainCommitOnly() {}
+
+ProxyImpl::~ProxyImpl() {
+ TRACE_EVENT0("cc", "ProxyImpl::~ProxyImpl");
+ DCHECK(IsImplThread());
+ DCHECK(IsMainThreadBlocked());
+
+ scheduler_ = nullptr;
+ external_begin_frame_source_ = nullptr;
+ layer_tree_host_impl_ = nullptr;
+ // We need to explicitly shutdown the notifier to destroy any weakptrs it is
+ // holding while still on the compositor thread. This also ensures any
+ // callbacks holding a ProxyImpl pointer are cancelled.
+ smoothness_priority_expiration_notifier_.Shutdown();
+}
+
+void ProxyImpl::SetThrottleFrameProductionOnImpl(bool throttle) {
+ TRACE_EVENT1("cc", "ProxyImpl::SetThrottleFrameProductionOnImplThread",
+ "throttle", throttle);
+ DCHECK(IsImplThread());
+ scheduler_->SetThrottleFrameProduction(throttle);
+}
+
+void ProxyImpl::UpdateTopControlsStateOnImpl(TopControlsState constraints,
+ TopControlsState current,
+ bool animate) {
+ DCHECK(IsImplThread());
+ layer_tree_host_impl_->top_controls_manager()->UpdateTopControlsState(
+ constraints, current, animate);
+}
+
+void ProxyImpl::InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) {
+ TRACE_EVENT0("cc", "ProxyImpl::InitializeOutputSurfaceOnImplThread");
+ DCHECK(IsImplThread());
+
+ LayerTreeHostImpl* host_impl = layer_tree_host_impl_.get();
+ bool success = host_impl->InitializeRenderer(output_surface);
+ RendererCapabilities capabilities;
+ if (success) {
+ capabilities =
+ host_impl->GetRendererCapabilities().MainThreadCapabilities();
+ }
+
+ channel_impl_->DidInitializeOutputSurface(success, capabilities);
+
+ if (success)
+ scheduler_->DidCreateAndInitializeOutputSurface();
+}
+
+void ProxyImpl::MainThreadHasStoppedFlingingOnImpl() {
+ DCHECK(IsImplThread());
+ layer_tree_host_impl_->MainThreadHasStoppedFlinging();
+}
+
+void ProxyImpl::SetInputThrottledUntilCommitOnImpl(bool is_throttled) {
+ DCHECK(IsImplThread());
+ if (is_throttled == input_throttled_until_commit_)
+ return;
+ input_throttled_until_commit_ = is_throttled;
+ RenewTreePriority();
+}
+
+void ProxyImpl::SetDeferCommitsOnImpl(bool defer_commits) const {
+ DCHECK(IsImplThread());
+ scheduler_->SetDeferCommits(defer_commits);
+}
+
+void ProxyImpl::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
+ DCHECK(IsImplThread());
+ SetNeedsRedrawRectOnImplThread(damage_rect);
+}
+
+void ProxyImpl::SetNeedsCommitOnImpl() {
+ DCHECK(IsImplThread());
+ SetNeedsCommitOnImplThread();
+}
+
+void ProxyImpl::BeginMainFrameAbortedOnImpl(
+ CommitEarlyOutReason reason,
+ base::TimeTicks main_thread_start_time) {
+ TRACE_EVENT1("cc", "ProxyImpl::BeginMainFrameAbortedOnImplThread", "reason",
+ CommitEarlyOutReasonToString(reason));
+ DCHECK(IsImplThread());
+ DCHECK(scheduler_->CommitPending());
+ DCHECK(!layer_tree_host_impl_->pending_tree());
+
+ if (CommitEarlyOutHandledCommit(reason)) {
+ SetInputThrottledUntilCommitOnImpl(false);
+ last_processed_begin_main_frame_args_ = last_begin_main_frame_args_;
+ }
+ layer_tree_host_impl_->BeginMainFrameAborted(reason);
+ scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time);
+ scheduler_->BeginMainFrameAborted(reason);
+}
+
+void ProxyImpl::FinishAllRenderingOnImpl(CompletionEvent* completion) {
+ TRACE_EVENT0("cc", "ProxyImpl::FinishAllRenderingOnImplThread");
+ DCHECK(IsImplThread());
+ layer_tree_host_impl_->FinishAllRendering();
+ completion->Signal();
+}
+
+void ProxyImpl::SetVisibleOnImpl(bool visible) {
+ TRACE_EVENT1("cc", "ProxyImpl::SetVisibleOnImplThread", "visible", visible);
+ DCHECK(IsImplThread());
+ layer_tree_host_impl_->SetVisible(visible);
+ scheduler_->SetVisible(visible);
+}
+
+void ProxyImpl::ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) {
+ DCHECK(IsImplThread());
+
+ // Unlike DidLoseOutputSurfaceOnImplThread, we don't need to call
+ // LayerTreeHost::DidLoseOutputSurface since it already knows.
+ scheduler_->DidLoseOutputSurface();
+ layer_tree_host_impl_->ReleaseOutputSurface();
+ completion->Signal();
+}
+
+void ProxyImpl::FinishGLOnImpl(CompletionEvent* completion) {
+ TRACE_EVENT0("cc", "ProxyImpl::FinishGLOnImplThread");
+ DCHECK(IsImplThread());
+ if (layer_tree_host_impl_->output_surface()) {
+ ContextProvider* context_provider =
+ layer_tree_host_impl_->output_surface()->context_provider();
+ if (context_provider)
+ context_provider->ContextGL()->Finish();
+ }
+ completion->Signal();
+}
+
+void ProxyImpl::MainFrameWillHappenOnImplForTesting(
+ CompletionEvent* completion,
+ bool* main_frame_will_happen) {
+ DCHECK(IsImplThread());
+ if (layer_tree_host_impl_->output_surface()) {
+ *main_frame_will_happen = scheduler_->MainFrameForTestingWillHappen();
+ } else {
+ *main_frame_will_happen = false;
+ }
+ completion->Signal();
+}
+
+void ProxyImpl::StartCommitOnImpl(CompletionEvent* completion,
+ LayerTreeHost* layer_tree_host,
+ base::TimeTicks main_thread_start_time,
+ bool hold_commit_for_activation) {
+ TRACE_EVENT0("cc", "ProxyImpl::StartCommitOnImplThread");
+ DCHECK(!commit_completion_event_);
+ DCHECK(IsImplThread() && IsMainThreadBlocked());
+ DCHECK(scheduler_);
+ DCHECK(scheduler_->CommitPending());
+
+ if (hold_commit_for_activation) {
+ // This commit may be aborted. Store the value for
+ // hold_commit_for_activation so that whenever the next commit is started,
+ // the main thread will be unblocked only after pending tree activation.
+ next_commit_waits_for_activation_ = hold_commit_for_activation;
+ }
+
+ if (!layer_tree_host_impl_) {
+ TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoLayerTree",
+ TRACE_EVENT_SCOPE_THREAD);
+ completion->Signal();
+ return;
+ }
+
+ // Ideally, we should inform to impl thread when BeginMainFrame is started.
+ // But, we can avoid a PostTask in here.
+ scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time);
+ commit_completion_event_ = completion;
+ DCHECK(!blocked_main_commit().layer_tree_host);
+ blocked_main_commit().layer_tree_host = layer_tree_host;
+ scheduler_->NotifyReadyToCommit();
+}
+
+void ProxyImpl::UpdateRendererCapabilitiesOnImplThread() {
+ DCHECK(IsImplThread());
+ channel_impl_->SetRendererCapabilitiesMainCopy(
+ layer_tree_host_impl_->GetRendererCapabilities()
+ .MainThreadCapabilities());
+}
+
+void ProxyImpl::DidLoseOutputSurfaceOnImplThread() {
+ TRACE_EVENT0("cc", "ProxyImpl::DidLoseOutputSurfaceOnImplThread");
+ DCHECK(IsImplThread());
+ channel_impl_->DidLoseOutputSurface();
+ scheduler_->DidLoseOutputSurface();
+}
+
+void ProxyImpl::CommitVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ DCHECK(IsImplThread());
+ scheduler_->CommitVSyncParameters(timebase, interval);
+}
+
+void ProxyImpl::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
+ DCHECK(IsImplThread());
+ scheduler_->SetEstimatedParentDrawTime(draw_time);
+}
+
+void ProxyImpl::DidSwapBuffersOnImplThread() {
+ DCHECK(IsImplThread());
+ scheduler_->DidSwapBuffers();
+}
+
+void ProxyImpl::DidSwapBuffersCompleteOnImplThread() {
+ TRACE_EVENT0("cc,benchmark", "ProxyImpl::DidSwapBuffersCompleteOnImplThread");
+ DCHECK(IsImplThread());
+ scheduler_->DidSwapBuffersComplete();
+ channel_impl_->DidCompleteSwapBuffers();
+}
+
+void ProxyImpl::OnResourcelessSoftareDrawStateChanged(bool resourceless_draw) {
+ DCHECK(IsImplThread());
+ scheduler_->SetResourcelessSoftareDraw(resourceless_draw);
+}
+
+void ProxyImpl::OnCanDrawStateChanged(bool can_draw) {
+ TRACE_EVENT1("cc", "ProxyImpl::OnCanDrawStateChanged", "can_draw", can_draw);
+ DCHECK(IsImplThread());
+ scheduler_->SetCanDraw(can_draw);
+}
+
+void ProxyImpl::NotifyReadyToActivate() {
+ TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToActivate");
+ DCHECK(IsImplThread());
+ scheduler_->NotifyReadyToActivate();
+}
+
+void ProxyImpl::NotifyReadyToDraw() {
+ TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToDraw");
+ DCHECK(IsImplThread());
+ scheduler_->NotifyReadyToDraw();
+}
+
+void ProxyImpl::SetNeedsRedrawOnImplThread() {
+ TRACE_EVENT0("cc", "ProxyImpl::SetNeedsRedrawOnImplThread");
+ DCHECK(IsImplThread());
+ scheduler_->SetNeedsRedraw();
+}
+
+void ProxyImpl::SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) {
+ DCHECK(IsImplThread());
+ layer_tree_host_impl_->SetViewportDamage(damage_rect);
+ SetNeedsRedrawOnImplThread();
+}
+
+void ProxyImpl::SetNeedsOneBeginImplFrameOnImplThread() {
+ TRACE_EVENT0("cc", "ProxyImpl::SetNeedsOneBeginImplFrameOnImplThread");
+ DCHECK(IsImplThread());
+ scheduler_->SetNeedsOneBeginImplFrame();
+}
+
+void ProxyImpl::SetNeedsPrepareTilesOnImplThread() {
+ DCHECK(IsImplThread());
+ scheduler_->SetNeedsPrepareTiles();
+}
+
+void ProxyImpl::SetNeedsCommitOnImplThread() {
+ TRACE_EVENT0("cc", "ProxyImpl::SetNeedsCommitOnImplThread");
+ DCHECK(IsImplThread());
+ scheduler_->SetNeedsBeginMainFrame();
+}
+
+void ProxyImpl::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
+ TRACE_EVENT1("cc", "ProxyImpl::SetVideoNeedsBeginFrames",
+ "needs_begin_frames", needs_begin_frames);
+ DCHECK(IsImplThread());
+ // In tests the layer tree is destroyed after the scheduler is.
+ if (scheduler_)
+ scheduler_->SetVideoNeedsBeginFrames(needs_begin_frames);
+}
+
+void ProxyImpl::PostAnimationEventsToMainThreadOnImplThread(
+ scoped_ptr<AnimationEventsVector> events) {
+ TRACE_EVENT0("cc", "ProxyImpl::PostAnimationEventsToMainThreadOnImplThread");
+ DCHECK(IsImplThread());
+ channel_impl_->SetAnimationEvents(std::move(events));
+}
+
+bool ProxyImpl::IsInsideDraw() {
+ return inside_draw_;
+}
+
+void ProxyImpl::RenewTreePriority() {
+ DCHECK(IsImplThread());
+ bool smoothness_takes_priority =
+ layer_tree_host_impl_->pinch_gesture_active() ||
+ layer_tree_host_impl_->page_scale_animation_active() ||
+ layer_tree_host_impl_->IsActivelyScrolling();
+
+ // Schedule expiration if smoothness currently takes priority.
+ if (smoothness_takes_priority)
+ smoothness_priority_expiration_notifier_.Schedule();
+
+ // We use the same priority for both trees by default.
+ TreePriority tree_priority = SAME_PRIORITY_FOR_BOTH_TREES;
+
+ // Smoothness takes priority if we have an expiration for it scheduled.
+ if (smoothness_priority_expiration_notifier_.HasPendingNotification())
+ tree_priority = SMOOTHNESS_TAKES_PRIORITY;
+
+ // New content always takes priority when there is an invalid viewport size or
+ // ui resources have been evicted.
+ if (layer_tree_host_impl_->active_tree()->ViewportSizeInvalid() ||
+ layer_tree_host_impl_->EvictedUIResourcesExist() ||
+ input_throttled_until_commit_) {
+ // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active
+ // tree might be freed. We need to set RequiresHighResToDraw to ensure that
+ // high res tiles will be required to activate pending tree.
+ layer_tree_host_impl_->SetRequiresHighResToDraw();
+ tree_priority = NEW_CONTENT_TAKES_PRIORITY;
+ }
+
+ layer_tree_host_impl_->SetTreePriority(tree_priority);
+
+ // Only put the scheduler in impl latency prioritization mode if we don't
+ // have a scroll listener. This gives the scroll listener a better chance of
+ // handling scroll updates within the same frame. The tree itself is still
+ // kept in prefer smoothness mode to allow checkerboarding.
+ ScrollHandlerState scroll_handler_state =
+ layer_tree_host_impl_->scroll_affects_scroll_handler()
+ ? ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER
+ : ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
+ scheduler_->SetTreePrioritiesAndScrollState(tree_priority,
+ scroll_handler_state);
+
+ // Notify the the client of this compositor via the output surface.
+ // TODO(epenner): Route this to compositor-thread instead of output-surface
+ // after GTFO refactor of compositor-thread (http://crbug/170828).
+ if (layer_tree_host_impl_->output_surface()) {
+ layer_tree_host_impl_->output_surface()->UpdateSmoothnessTakesPriority(
+ tree_priority == SMOOTHNESS_TAKES_PRIORITY);
+ }
+}
+
+void ProxyImpl::PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
+ base::TimeDelta delay) {
+ DCHECK(IsImplThread());
+ task_runner_provider_->ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE,
+ task, delay);
+}
+
+void ProxyImpl::DidActivateSyncTree() {
+ TRACE_EVENT0("cc", "ProxyImpl::DidActivateSyncTreeOnImplThread");
+ DCHECK(IsImplThread());
+
+ if (next_commit_waits_for_activation_) {
+ TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation",
+ TRACE_EVENT_SCOPE_THREAD);
+ DCHECK(commit_completion_event_);
+ commit_completion_event_->Signal();
+ commit_completion_event_ = nullptr;
+ next_commit_waits_for_activation_ = false;
+ }
+
+ last_processed_begin_main_frame_args_ = last_begin_main_frame_args_;
+}
+
+void ProxyImpl::WillPrepareTiles() {
+ DCHECK(IsImplThread());
+ scheduler_->WillPrepareTiles();
+}
+
+void ProxyImpl::DidPrepareTiles() {
+ DCHECK(IsImplThread());
+ scheduler_->DidPrepareTiles();
+}
+
+void ProxyImpl::DidCompletePageScaleAnimationOnImplThread() {
+ DCHECK(IsImplThread());
+ channel_impl_->DidCompletePageScaleAnimation();
+}
+
+void ProxyImpl::OnDrawForOutputSurface() {
+ DCHECK(IsImplThread());
+ scheduler_->OnDrawForOutputSurface();
+}
+
+void ProxyImpl::PostFrameTimingEventsOnImplThread(
+ scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
+ scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
+ DCHECK(IsImplThread());
+ channel_impl_->PostFrameTimingEventsOnMain(std::move(composite_events),
+ std::move(main_frame_events));
+}
+
+void ProxyImpl::WillBeginImplFrame(const BeginFrameArgs& args) {
+ DCHECK(IsImplThread());
+ layer_tree_host_impl_->WillBeginImplFrame(args);
+ if (last_processed_begin_main_frame_args_.IsValid()) {
+ // Last processed begin main frame args records the frame args that we sent
+ // to the main thread for the last frame that we've processed. If that is
+ // set, that means the current frame is one past the frame in which we've
+ // finished the processing.
+ layer_tree_host_impl_->RecordMainFrameTiming(
+ last_processed_begin_main_frame_args_, args);
+ last_processed_begin_main_frame_args_ = BeginFrameArgs();
+ }
+}
+
+void ProxyImpl::DidFinishImplFrame() {
+ DCHECK(IsImplThread());
+ layer_tree_host_impl_->DidFinishImplFrame();
+}
+
+void ProxyImpl::ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) {
+ DCHECK(IsImplThread());
+ unsigned int begin_frame_id = nextBeginFrameId++;
+ benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
+ benchmark_instrumentation::kSendBeginFrame, begin_frame_id);
+ scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state(
+ new BeginMainFrameAndCommitState);
+ begin_main_frame_state->begin_frame_id = begin_frame_id;
+ begin_main_frame_state->begin_frame_args = args;
+ begin_main_frame_state->scroll_info =
+ layer_tree_host_impl_->ProcessScrollDeltas();
+ begin_main_frame_state->memory_allocation_limit_bytes =
+ layer_tree_host_impl_->memory_allocation_limit_bytes();
+ begin_main_frame_state->evicted_ui_resources =
+ layer_tree_host_impl_->EvictedUIResourcesExist();
+ // TODO(vmpstr): This needs to be fixed if
+ // main_frame_before_activation_enabled is set, since we might run this code
+ // twice before recording a duration. crbug.com/469824
+ last_begin_main_frame_args_ = begin_main_frame_state->begin_frame_args;
+ channel_impl_->BeginMainFrame(std::move(begin_main_frame_state));
+ devtools_instrumentation::DidRequestMainThreadFrame(layer_tree_host_id_);
+}
+
+DrawResult ProxyImpl::ScheduledActionDrawAndSwapIfPossible() {
+ TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionDrawAndSwap");
+ DCHECK(IsImplThread());
+
+ // SchedulerStateMachine::DidDrawIfPossibleCompleted isn't set up to
+ // handle DRAW_ABORTED_CANT_DRAW. Moreover, the scheduler should
+ // never generate this call when it can't draw.
+ DCHECK(layer_tree_host_impl_->CanDraw());
+
+ bool forced_draw = false;
+ return DrawAndSwapInternal(forced_draw);
+}
+
+DrawResult ProxyImpl::ScheduledActionDrawAndSwapForced() {
+ TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionDrawAndSwapForced");
+ DCHECK(IsImplThread());
+ bool forced_draw = true;
+ return DrawAndSwapInternal(forced_draw);
+}
+
+void ProxyImpl::ScheduledActionCommit() {
+ TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionCommit");
+ DCHECK(IsImplThread());
+ DCHECK(IsMainThreadBlocked());
+ DCHECK(commit_completion_event_);
+
+ layer_tree_host_impl_->BeginCommit();
+ blocked_main_commit().layer_tree_host->FinishCommitOnImplThread(
+ layer_tree_host_impl_.get());
+
+ // Remove the LayerTreeHost reference before the completion event is signaled
+ // and cleared. This is necessary since blocked_main_commit() allows access
+ // only while we have the completion event to ensure the main thread is
+ // blocked for a commit.
+ blocked_main_commit().layer_tree_host = nullptr;
+
+ if (next_commit_waits_for_activation_) {
+ // For some layer types in impl-side painting, the commit is held until
+ // the sync tree is activated. It's also possible that the
+ // sync tree has already activated if there was no work to be done.
+ TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
+ } else {
+ commit_completion_event_->Signal();
+ commit_completion_event_ = nullptr;
+ }
+
+ scheduler_->DidCommit();
+
+ // Delay this step until afer the main thread has been released as it's
+ // often a good bit of work to update the tree and prepare the new frame.
+ layer_tree_host_impl_->CommitComplete();
+
+ SetInputThrottledUntilCommitOnImpl(false);
+
+ next_frame_is_newly_committed_frame_ = true;
+}
+
+void ProxyImpl::ScheduledActionActivateSyncTree() {
+ TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionActivateSyncTree");
+ DCHECK(IsImplThread());
+ layer_tree_host_impl_->ActivateSyncTree();
+}
+
+void ProxyImpl::ScheduledActionBeginOutputSurfaceCreation() {
+ TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionBeginOutputSurfaceCreation");
+ DCHECK(IsImplThread());
+ channel_impl_->RequestNewOutputSurface();
+}
+
+void ProxyImpl::ScheduledActionPrepareTiles() {
+ TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionPrepareTiles");
+ DCHECK(IsImplThread());
+ layer_tree_host_impl_->PrepareTiles();
+}
+
+void ProxyImpl::ScheduledActionInvalidateOutputSurface() {
+ TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionInvalidateOutputSurface");
+ DCHECK(IsImplThread());
+ DCHECK(layer_tree_host_impl_->output_surface());
+ layer_tree_host_impl_->output_surface()->Invalidate();
+}
+
+void ProxyImpl::SendBeginFramesToChildren(const BeginFrameArgs& args) {
+ NOTREACHED() << "Only used by SingleThreadProxy";
+}
+
+void ProxyImpl::SendBeginMainFrameNotExpectedSoon() {
+ DCHECK(IsImplThread());
+ channel_impl_->BeginMainFrameNotExpectedSoon();
+}
+
+DrawResult ProxyImpl::DrawAndSwapInternal(bool forced_draw) {
+ TRACE_EVENT_SYNTHETIC_DELAY("cc.DrawAndSwap");
+
+ DCHECK(IsImplThread());
+ DCHECK(layer_tree_host_impl_.get());
+
+ base::AutoReset<bool> mark_inside(&inside_draw_, true);
+
+ if (layer_tree_host_impl_->pending_tree()) {
+ bool update_lcd_text = false;
+ layer_tree_host_impl_->pending_tree()->UpdateDrawProperties(
+ update_lcd_text);
+ }
+
+ // This method is called on a forced draw, regardless of whether we are able
+ // to produce a frame, as the calling site on main thread is blocked until its
+ // request completes, and we signal completion here. If CanDraw() is false, we
+ // will indicate success=false to the caller, but we must still signal
+ // completion to avoid deadlock.
+
+ // We guard PrepareToDraw() with CanDraw() because it always returns a valid
+ // frame, so can only be used when such a frame is possible. Since
+ // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
+ // CanDraw() as well.
+
+ LayerTreeHostImpl::FrameData frame;
+ bool draw_frame = false;
+
+ DrawResult result;
+ if (layer_tree_host_impl_->CanDraw()) {
+ result = layer_tree_host_impl_->PrepareToDraw(&frame);
+ draw_frame = forced_draw || result == DRAW_SUCCESS;
+ } else {
+ result = DRAW_ABORTED_CANT_DRAW;
+ }
+
+ if (draw_frame) {
+ layer_tree_host_impl_->DrawLayers(&frame);
+ result = DRAW_SUCCESS;
+ } else {
+ DCHECK_NE(DRAW_SUCCESS, result);
+ }
+ layer_tree_host_impl_->DidDrawAllLayers(frame);
+
+ bool start_ready_animations = draw_frame;
+ layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
+
+ if (draw_frame)
+ layer_tree_host_impl_->SwapBuffers(frame);
+
+ // Tell the main thread that the the newly-commited frame was drawn.
+ if (next_frame_is_newly_committed_frame_) {
+ next_frame_is_newly_committed_frame_ = false;
+ channel_impl_->DidCommitAndDrawFrame();
+ }
+
+ DCHECK_NE(INVALID_RESULT, result);
+ return result;
+}
+
+bool ProxyImpl::IsImplThread() const {
+ return task_runner_provider_->IsImplThread();
+}
+
+bool ProxyImpl::IsMainThreadBlocked() const {
+ return task_runner_provider_->IsMainThreadBlocked();
+}
+
+ProxyImpl::BlockedMainCommitOnly& ProxyImpl::blocked_main_commit() {
+ DCHECK(IsMainThreadBlocked() && commit_completion_event_);
+ return main_thread_blocked_commit_vars_unsafe_;
+}
+
+} // namespace cc
diff --git a/cc/trees/proxy_impl.h b/cc/trees/proxy_impl.h
index 4b0cdaa..092385b 100644
--- a/cc/trees/proxy_impl.h
+++ b/cc/trees/proxy_impl.h
@@ -5,59 +5,171 @@
#ifndef CC_TREES_PROXY_IMPL_H_
#define CC_TREES_PROXY_IMPL_H_
-#include "base/memory/weak_ptr.h"
-#include "cc/base/cc_export.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "cc/base/completion_event.h"
+#include "cc/base/delayed_unique_notifier.h"
#include "cc/input/top_controls_state.h"
-#include "cc/output/output_surface.h"
-#include "cc/scheduler/commit_earlyout_reason.h"
-#include "cc/trees/proxy_common.h"
+#include "cc/scheduler/scheduler.h"
+#include "cc/trees/channel_impl.h"
+#include "cc/trees/layer_tree_host_impl.h"
namespace cc {
-// TODO(khushalsagar): The impl side of ThreadProxy. It is currently defined as
-// an interface with the implementation provided by ThreadProxy and will be
-// made an independent class.
-// The methods added to this interface should only use the CompositorThreadOnly
-// variables from ThreadProxy.
-// See crbug/527200
-class CC_EXPORT ProxyImpl {
- private:
- friend class ThreadedChannel;
- // Callback for impl side commands received from the channel.
- virtual void SetThrottleFrameProductionOnImpl(bool throttle) = 0;
+// This class aggregates all the interactions that the main side of the
+// compositor needs to have with the impl side. It is created and owned by the
+// ChannelImpl implementation. The class lives entirely on the impl thread.
+class CC_EXPORT ProxyImpl : public NON_EXPORTED_BASE(LayerTreeHostImplClient),
+ public NON_EXPORTED_BASE(SchedulerClient) {
+ public:
+ static scoped_ptr<ProxyImpl> Create(
+ ChannelImpl* channel_impl,
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+ ~ProxyImpl() override;
+
+ // Virtual for testing.
+ virtual void SetThrottleFrameProductionOnImpl(bool throttle);
virtual void UpdateTopControlsStateOnImpl(TopControlsState constraints,
TopControlsState current,
- bool animate) = 0;
- virtual void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) = 0;
- virtual void MainThreadHasStoppedFlingingOnImpl() = 0;
- virtual void SetInputThrottledUntilCommitOnImpl(bool is_throttled) = 0;
- virtual void SetDeferCommitsOnImpl(bool defer_commits) const = 0;
- virtual void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) = 0;
- virtual void SetNeedsCommitOnImpl() = 0;
- virtual void FinishAllRenderingOnImpl(CompletionEvent* completion) = 0;
- virtual void SetVisibleOnImpl(bool visible) = 0;
- virtual void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) = 0;
- virtual void FinishGLOnImpl(CompletionEvent* completion) = 0;
- virtual void MainFrameWillHappenOnImplForTesting(
- CompletionEvent* completion,
- bool* main_frame_will_happen) = 0;
+ bool animate);
+ virtual void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface);
+ virtual void MainThreadHasStoppedFlingingOnImpl();
+ virtual void SetInputThrottledUntilCommitOnImpl(bool is_throttled);
+ virtual void SetDeferCommitsOnImpl(bool defer_commits) const;
+ virtual void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect);
+ virtual void SetNeedsCommitOnImpl();
virtual void BeginMainFrameAbortedOnImpl(
CommitEarlyOutReason reason,
- base::TimeTicks main_thread_start_time) = 0;
+ base::TimeTicks main_thread_start_time);
+ virtual void FinishAllRenderingOnImpl(CompletionEvent* completion);
+ virtual void SetVisibleOnImpl(bool visible);
+ virtual void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion);
+ virtual void FinishGLOnImpl(CompletionEvent* completion);
+ virtual void MainFrameWillHappenOnImplForTesting(
+ CompletionEvent* completion,
+ bool* main_frame_will_happen);
virtual void StartCommitOnImpl(CompletionEvent* completion,
LayerTreeHost* layer_tree_host,
base::TimeTicks main_thread_start_time,
- bool hold_commit_for_activation) = 0;
- virtual void InitializeImplOnImpl(CompletionEvent* completion,
- LayerTreeHost* layer_tree_host) = 0;
- virtual void LayerTreeHostClosedOnImpl(CompletionEvent* completion) = 0;
-
- // TODO(khushalsagar): Rename as GetWeakPtr() once ThreadProxy is split.
- virtual base::WeakPtr<ProxyImpl> GetImplWeakPtr() = 0;
+ bool hold_commit_for_activation);
protected:
- virtual ~ProxyImpl() {}
+ // protected for testing.
+ ProxyImpl(ChannelImpl* channel_impl,
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+ private:
+ // The members of this struct should be accessed on the impl thread only when
+ // the main thread is blocked for a commit.
+ struct BlockedMainCommitOnly {
+ BlockedMainCommitOnly();
+ ~BlockedMainCommitOnly();
+ LayerTreeHost* layer_tree_host;
+ };
+
+ friend class ProxyImplForTest;
+
+ // LayerTreeHostImplClient implementation
+ void UpdateRendererCapabilitiesOnImplThread() override;
+ void DidLoseOutputSurfaceOnImplThread() override;
+ void CommitVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) override;
+ void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override;
+ void DidSwapBuffersOnImplThread() override;
+ void DidSwapBuffersCompleteOnImplThread() override;
+ void OnResourcelessSoftareDrawStateChanged(bool resourceless_draw) override;
+ void OnCanDrawStateChanged(bool can_draw) override;
+ void NotifyReadyToActivate() override;
+ void NotifyReadyToDraw() override;
+ // Please call these 3 functions through
+ // LayerTreeHostImpl's SetNeedsRedraw(), SetNeedsRedrawRect() and
+ // SetNeedsOneBeginImplFrame().
+ void SetNeedsRedrawOnImplThread() override;
+ void SetNeedsRedrawRectOnImplThread(const gfx::Rect& dirty_rect) override;
+ void SetNeedsOneBeginImplFrameOnImplThread() override;
+ void SetNeedsPrepareTilesOnImplThread() override;
+ void SetNeedsCommitOnImplThread() override;
+ void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
+ void PostAnimationEventsToMainThreadOnImplThread(
+ scoped_ptr<AnimationEventsVector> queue) override;
+ bool IsInsideDraw() override;
+ void RenewTreePriority() override;
+ void PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
+ base::TimeDelta delay) override;
+ void DidActivateSyncTree() override;
+ void WillPrepareTiles() override;
+ void DidPrepareTiles() override;
+ void DidCompletePageScaleAnimationOnImplThread() override;
+ void OnDrawForOutputSurface() override;
+ // This should only be called by LayerTreeHostImpl::PostFrameTimingEvents.
+ void PostFrameTimingEventsOnImplThread(
+ scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
+ scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
+ override;
+
+ // SchedulerClient implementation
+ void WillBeginImplFrame(const BeginFrameArgs& args) override;
+ void DidFinishImplFrame() override;
+ void ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) override;
+ DrawResult ScheduledActionDrawAndSwapIfPossible() override;
+ DrawResult ScheduledActionDrawAndSwapForced() override;
+ void ScheduledActionCommit() override;
+ void ScheduledActionActivateSyncTree() override;
+ void ScheduledActionBeginOutputSurfaceCreation() override;
+ void ScheduledActionPrepareTiles() override;
+ void ScheduledActionInvalidateOutputSurface() override;
+ void SendBeginFramesToChildren(const BeginFrameArgs& args) override;
+ void SendBeginMainFrameNotExpectedSoon() override;
+
+ DrawResult DrawAndSwapInternal(bool forced_draw);
+
+ bool IsImplThread() const;
+ bool IsMainThreadBlocked() const;
+
+ const int layer_tree_host_id_;
+
+ scoped_ptr<Scheduler> scheduler_;
+
+ // Set when the main thread is waiting on a pending tree activation.
+ bool next_commit_waits_for_activation_;
+
+ // Set when the main thread is waiting on a commit to complete or on a
+ // pending tree activation.
+ CompletionEvent* commit_completion_event_;
+
+ // Set when the next draw should post DidCommitAndDrawFrame to the main
+ // thread.
+ bool next_frame_is_newly_committed_frame_;
+
+ bool inside_draw_;
+ bool input_throttled_until_commit_;
+
+ TaskRunnerProvider* task_runner_provider_;
+
+ DelayedUniqueNotifier smoothness_priority_expiration_notifier_;
+
+ scoped_ptr<BeginFrameSource> external_begin_frame_source_;
+
+ RenderingStatsInstrumentation* rendering_stats_instrumentation_;
+
+ // Values used to keep track of frame durations. Used only in frame timing.
+ BeginFrameArgs last_begin_main_frame_args_;
+ BeginFrameArgs last_processed_begin_main_frame_args_;
+
+ scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl_;
+
+ ChannelImpl* channel_impl_;
+
+ // Use accessors instead of this variable directly.
+ BlockedMainCommitOnly main_thread_blocked_commit_vars_unsafe_;
+ BlockedMainCommitOnly& blocked_main_commit();
+
+ DISALLOW_COPY_AND_ASSIGN(ProxyImpl);
};
} // namespace cc
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
new file mode 100644
index 0000000..dd5ac1a
--- /dev/null
+++ b/cc/trees/proxy_main.cc
@@ -0,0 +1,465 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/trees/proxy_main.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_argument.h"
+#include "base/trace_event/trace_event_synthetic_delay.h"
+#include "cc/debug/benchmark_instrumentation.h"
+#include "cc/debug/devtools_instrumentation.h"
+#include "cc/output/output_surface.h"
+#include "cc/output/swap_promise.h"
+#include "cc/trees/blocking_task_runner.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/scoped_abort_remaining_swap_promises.h"
+#include "cc/trees/threaded_channel.h"
+
+namespace cc {
+
+scoped_ptr<ProxyMain> ProxyMain::CreateThreaded(
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+ scoped_ptr<ProxyMain> proxy_main(
+ new ProxyMain(layer_tree_host, task_runner_provider,
+ std::move(external_begin_frame_source)));
+ proxy_main->SetChannel(
+ ThreadedChannel::Create(proxy_main.get(), task_runner_provider));
+ return proxy_main;
+}
+
+ProxyMain::ProxyMain(LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source)
+ : layer_tree_host_(layer_tree_host),
+ task_runner_provider_(task_runner_provider),
+ layer_tree_host_id_(layer_tree_host->id()),
+ max_requested_pipeline_stage_(NO_PIPELINE_STAGE),
+ current_pipeline_stage_(NO_PIPELINE_STAGE),
+ final_pipeline_stage_(NO_PIPELINE_STAGE),
+ commit_waits_for_activation_(false),
+ started_(false),
+ defer_commits_(false),
+ external_begin_frame_source_(std::move(external_begin_frame_source)) {
+ TRACE_EVENT0("cc", "ProxyMain::ProxyMain");
+ DCHECK(task_runner_provider_);
+ DCHECK(IsMainThread());
+ DCHECK(!layer_tree_host_->settings().use_external_begin_frame_source ||
+ external_begin_frame_source_);
+}
+
+ProxyMain::~ProxyMain() {
+ TRACE_EVENT0("cc", "ProxyMain::~ProxyMain");
+ DCHECK(IsMainThread());
+ DCHECK(!started_);
+}
+
+void ProxyMain::SetChannel(scoped_ptr<ChannelMain> channel_main) {
+ DCHECK(!channel_main_);
+ channel_main_ = std::move(channel_main);
+}
+
+void ProxyMain::DidCompleteSwapBuffers() {
+ DCHECK(IsMainThread());
+ layer_tree_host_->DidCompleteSwapBuffers();
+}
+
+void ProxyMain::SetRendererCapabilities(
+ const RendererCapabilities& capabilities) {
+ DCHECK(IsMainThread());
+ renderer_capabilities_ = capabilities;
+}
+
+void ProxyMain::BeginMainFrameNotExpectedSoon() {
+ TRACE_EVENT0("cc", "ProxyMain::BeginMainFrameNotExpectedSoon");
+ DCHECK(IsMainThread());
+ layer_tree_host_->BeginMainFrameNotExpectedSoon();
+}
+
+void ProxyMain::DidCommitAndDrawFrame() {
+ DCHECK(IsMainThread());
+ layer_tree_host_->DidCommitAndDrawFrame();
+}
+
+void ProxyMain::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
+ TRACE_EVENT0("cc", "ProxyMain::SetAnimationEvents");
+ DCHECK(IsMainThread());
+ layer_tree_host_->SetAnimationEvents(std::move(events));
+}
+
+void ProxyMain::DidLoseOutputSurface() {
+ TRACE_EVENT0("cc", "ProxyMain::DidLoseOutputSurface");
+ DCHECK(IsMainThread());
+ layer_tree_host_->DidLoseOutputSurface();
+}
+
+void ProxyMain::RequestNewOutputSurface() {
+ DCHECK(IsMainThread());
+ layer_tree_host_->RequestNewOutputSurface();
+}
+
+void ProxyMain::DidInitializeOutputSurface(
+ bool success,
+ const RendererCapabilities& capabilities) {
+ TRACE_EVENT0("cc", "ProxyMain::DidInitializeOutputSurface");
+ DCHECK(IsMainThread());
+
+ if (!success) {
+ layer_tree_host_->DidFailToInitializeOutputSurface();
+ return;
+ }
+ renderer_capabilities_ = capabilities;
+ layer_tree_host_->DidInitializeOutputSurface();
+}
+
+void ProxyMain::DidCompletePageScaleAnimation() {
+ DCHECK(IsMainThread());
+ layer_tree_host_->DidCompletePageScaleAnimation();
+}
+
+void ProxyMain::PostFrameTimingEventsOnMain(
+ scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
+ scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
+ DCHECK(IsMainThread());
+ layer_tree_host_->RecordFrameTimingEvents(std::move(composite_events),
+ std::move(main_frame_events));
+}
+
+void ProxyMain::BeginMainFrame(
+ scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
+ benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
+ benchmark_instrumentation::kDoBeginFrame,
+ begin_main_frame_state->begin_frame_id);
+
+ base::TimeTicks begin_main_frame_start_time = base::TimeTicks::Now();
+
+ TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame");
+ DCHECK(IsMainThread());
+ DCHECK_EQ(NO_PIPELINE_STAGE, current_pipeline_stage_);
+
+ if (defer_commits_) {
+ TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
+ TRACE_EVENT_SCOPE_THREAD);
+ channel_main_->BeginMainFrameAbortedOnImpl(
+ CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT,
+ begin_main_frame_start_time);
+ return;
+ }
+
+ // If the commit finishes, LayerTreeHost will transfer its swap promises to
+ // LayerTreeImpl. The destructor of ScopedSwapPromiseChecker aborts the
+ // remaining swap promises.
+ ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
+
+ final_pipeline_stage_ = max_requested_pipeline_stage_;
+ max_requested_pipeline_stage_ = NO_PIPELINE_STAGE;
+
+ if (!layer_tree_host_->visible()) {
+ TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
+ channel_main_->BeginMainFrameAbortedOnImpl(
+ CommitEarlyOutReason::ABORTED_NOT_VISIBLE, begin_main_frame_start_time);
+ return;
+ }
+
+ if (layer_tree_host_->output_surface_lost()) {
+ TRACE_EVENT_INSTANT0("cc", "EarlyOut_OutputSurfaceLost",
+ TRACE_EVENT_SCOPE_THREAD);
+ channel_main_->BeginMainFrameAbortedOnImpl(
+ CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST,
+ begin_main_frame_start_time);
+ return;
+ }
+
+ current_pipeline_stage_ = ANIMATE_PIPELINE_STAGE;
+
+ layer_tree_host_->ApplyScrollAndScale(
+ begin_main_frame_state->scroll_info.get());
+
+ layer_tree_host_->WillBeginMainFrame();
+
+ layer_tree_host_->BeginMainFrame(begin_main_frame_state->begin_frame_args);
+ layer_tree_host_->AnimateLayers(
+ begin_main_frame_state->begin_frame_args.frame_time);
+
+ // Recreate all UI resources if there were evicted UI resources when the impl
+ // thread initiated the commit.
+ if (begin_main_frame_state->evicted_ui_resources)
+ layer_tree_host_->RecreateUIResources();
+
+ layer_tree_host_->RequestMainFrameUpdate();
+ TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
+
+ bool can_cancel_this_commit = final_pipeline_stage_ < COMMIT_PIPELINE_STAGE &&
+ !begin_main_frame_state->evicted_ui_resources;
+
+ current_pipeline_stage_ = UPDATE_LAYERS_PIPELINE_STAGE;
+ bool should_update_layers =
+ final_pipeline_stage_ >= UPDATE_LAYERS_PIPELINE_STAGE;
+ bool updated = should_update_layers && layer_tree_host_->UpdateLayers();
+
+ layer_tree_host_->WillCommit();
+ devtools_instrumentation::ScopedCommitTrace commit_task(
+ layer_tree_host_->id());
+
+ current_pipeline_stage_ = COMMIT_PIPELINE_STAGE;
+ if (!updated && can_cancel_this_commit) {
+ TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD);
+ channel_main_->BeginMainFrameAbortedOnImpl(
+ CommitEarlyOutReason::FINISHED_NO_UPDATES, begin_main_frame_start_time);
+
+ // Although the commit is internally aborted, this is because it has been
+ // detected to be a no-op. From the perspective of an embedder, this commit
+ // went through, and input should no longer be throttled, etc.
+ current_pipeline_stage_ = NO_PIPELINE_STAGE;
+ layer_tree_host_->CommitComplete();
+ layer_tree_host_->DidBeginMainFrame();
+ layer_tree_host_->BreakSwapPromises(SwapPromise::COMMIT_NO_UPDATE);
+ return;
+ }
+
+ // Notify the impl thread that the main thread is ready to commit. This will
+ // begin the commit process, which is blocking from the main thread's
+ // point of view, but asynchronously performed on the impl thread,
+ // coordinated by the Scheduler.
+ {
+ TRACE_EVENT0("cc", "ProxyMain::BeginMainFrame::commit");
+
+ DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+
+ // This CapturePostTasks should be destroyed before CommitComplete() is
+ // called since that goes out to the embedder, and we want the embedder
+ // to receive its callbacks before that.
+ BlockingTaskRunner::CapturePostTasks blocked(
+ task_runner_provider_->blocking_main_thread_task_runner());
+
+ bool hold_commit_for_activation = commit_waits_for_activation_;
+ commit_waits_for_activation_ = false;
+ CompletionEvent completion;
+ channel_main_->StartCommitOnImpl(&completion, layer_tree_host_,
+ begin_main_frame_start_time,
+ hold_commit_for_activation);
+ completion.Wait();
+ }
+
+ current_pipeline_stage_ = NO_PIPELINE_STAGE;
+ layer_tree_host_->CommitComplete();
+ layer_tree_host_->DidBeginMainFrame();
+}
+
+void ProxyMain::FinishAllRendering() {
+ DCHECK(IsMainThread());
+ DCHECK(!defer_commits_);
+
+ // Make sure all GL drawing is finished on the impl thread.
+ DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+ CompletionEvent completion;
+ channel_main_->FinishAllRenderingOnImpl(&completion);
+ completion.Wait();
+}
+
+bool ProxyMain::IsStarted() const {
+ DCHECK(IsMainThread());
+ return started_;
+}
+
+bool ProxyMain::CommitToActiveTree() const {
+ // With ProxyMain, we use a pending tree and activate it once it's ready to
+ // draw to allow input to modify the active tree and draw during raster.
+ return false;
+}
+
+void ProxyMain::SetOutputSurface(OutputSurface* output_surface) {
+ channel_main_->InitializeOutputSurfaceOnImpl(output_surface);
+}
+
+void ProxyMain::SetVisible(bool visible) {
+ TRACE_EVENT1("cc", "ProxyMain::SetVisible", "visible", visible);
+ channel_main_->SetVisibleOnImpl(visible);
+}
+
+void ProxyMain::SetThrottleFrameProduction(bool throttle) {
+ TRACE_EVENT1("cc", "ProxyMain::SetThrottleFrameProduction", "throttle",
+ throttle);
+ channel_main_->SetThrottleFrameProductionOnImpl(throttle);
+}
+
+const RendererCapabilities& ProxyMain::GetRendererCapabilities() const {
+ DCHECK(IsMainThread());
+ DCHECK(!layer_tree_host_->output_surface_lost());
+ return renderer_capabilities_;
+}
+
+void ProxyMain::SetNeedsAnimate() {
+ DCHECK(IsMainThread());
+ if (SendCommitRequestToImplThreadIfNeeded(ANIMATE_PIPELINE_STAGE)) {
+ TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsAnimate",
+ TRACE_EVENT_SCOPE_THREAD);
+ }
+}
+
+void ProxyMain::SetNeedsUpdateLayers() {
+ DCHECK(IsMainThread());
+ // If we are currently animating, make sure we also update the layers.
+ if (current_pipeline_stage_ == ANIMATE_PIPELINE_STAGE) {
+ final_pipeline_stage_ =
+ std::max(final_pipeline_stage_, UPDATE_LAYERS_PIPELINE_STAGE);
+ return;
+ }
+ if (SendCommitRequestToImplThreadIfNeeded(UPDATE_LAYERS_PIPELINE_STAGE)) {
+ TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsUpdateLayers",
+ TRACE_EVENT_SCOPE_THREAD);
+ }
+}
+
+void ProxyMain::SetNeedsCommit() {
+ DCHECK(IsMainThread());
+ // If we are currently animating, make sure we don't skip the commit. Note
+ // that requesting a commit during the layer update stage means we need to
+ // schedule another full commit.
+ if (current_pipeline_stage_ == ANIMATE_PIPELINE_STAGE) {
+ final_pipeline_stage_ =
+ std::max(final_pipeline_stage_, COMMIT_PIPELINE_STAGE);
+ return;
+ }
+ if (SendCommitRequestToImplThreadIfNeeded(COMMIT_PIPELINE_STAGE)) {
+ TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsCommit",
+ TRACE_EVENT_SCOPE_THREAD);
+ }
+}
+
+void ProxyMain::SetNeedsRedraw(const gfx::Rect& damage_rect) {
+ TRACE_EVENT0("cc", "ProxyMain::SetNeedsRedraw");
+ DCHECK(IsMainThread());
+ channel_main_->SetNeedsRedrawOnImpl(damage_rect);
+}
+
+void ProxyMain::SetNextCommitWaitsForActivation() {
+ DCHECK(IsMainThread());
+ commit_waits_for_activation_ = true;
+}
+
+void ProxyMain::NotifyInputThrottledUntilCommit() {
+ DCHECK(IsMainThread());
+ channel_main_->SetInputThrottledUntilCommitOnImpl(true);
+}
+
+void ProxyMain::SetDeferCommits(bool defer_commits) {
+ DCHECK(IsMainThread());
+ if (defer_commits_ == defer_commits)
+ return;
+
+ defer_commits_ = defer_commits;
+ if (defer_commits_)
+ TRACE_EVENT_ASYNC_BEGIN0("cc", "ProxyMain::SetDeferCommits", this);
+ else
+ TRACE_EVENT_ASYNC_END0("cc", "ProxyMain::SetDeferCommits", this);
+
+ channel_main_->SetDeferCommitsOnImpl(defer_commits);
+}
+
+bool ProxyMain::CommitRequested() const {
+ DCHECK(IsMainThread());
+ // TODO(skyostil): Split this into something like CommitRequested() and
+ // CommitInProgress().
+ return current_pipeline_stage_ != NO_PIPELINE_STAGE ||
+ max_requested_pipeline_stage_ >= COMMIT_PIPELINE_STAGE;
+}
+
+bool ProxyMain::BeginMainFrameRequested() const {
+ DCHECK(IsMainThread());
+ return max_requested_pipeline_stage_ != NO_PIPELINE_STAGE;
+}
+
+void ProxyMain::MainThreadHasStoppedFlinging() {
+ DCHECK(IsMainThread());
+ channel_main_->MainThreadHasStoppedFlingingOnImpl();
+}
+
+void ProxyMain::Start() {
+ DCHECK(IsMainThread());
+ DCHECK(task_runner_provider_->HasImplThread());
+ DCHECK(channel_main_);
+
+ // Create LayerTreeHostImpl.
+ channel_main_->SynchronouslyInitializeImpl(
+ layer_tree_host_, std::move(external_begin_frame_source_));
+
+ started_ = true;
+}
+
+void ProxyMain::Stop() {
+ TRACE_EVENT0("cc", "ProxyMain::Stop");
+ DCHECK(IsMainThread());
+ DCHECK(started_);
+
+ channel_main_->SynchronouslyCloseImpl();
+
+ layer_tree_host_ = nullptr;
+ started_ = false;
+}
+
+bool ProxyMain::SupportsImplScrolling() const {
+ return true;
+}
+
+bool ProxyMain::MainFrameWillHappenForTesting() {
+ DCHECK(IsMainThread());
+ bool main_frame_will_happen = false;
+ {
+ DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+ CompletionEvent completion;
+ channel_main_->MainFrameWillHappenOnImplForTesting(&completion,
+ &main_frame_will_happen);
+ completion.Wait();
+ }
+ return main_frame_will_happen;
+}
+
+void ProxyMain::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
+ NOTREACHED() << "Only used by SingleThreadProxy";
+}
+
+void ProxyMain::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) {
+ NOTREACHED() << "Only used by SingleProxyMain";
+}
+
+void ProxyMain::ReleaseOutputSurface() {
+ DCHECK(IsMainThread());
+ DCHECK(layer_tree_host_->output_surface_lost());
+
+ DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+ CompletionEvent completion;
+ channel_main_->ReleaseOutputSurfaceOnImpl(&completion);
+ completion.Wait();
+}
+
+void ProxyMain::UpdateTopControlsState(TopControlsState constraints,
+ TopControlsState current,
+ bool animate) {
+ DCHECK(IsMainThread());
+ channel_main_->UpdateTopControlsStateOnImpl(constraints, current, animate);
+}
+
+bool ProxyMain::SendCommitRequestToImplThreadIfNeeded(
+ CommitPipelineStage required_stage) {
+ DCHECK(IsMainThread());
+ DCHECK_NE(NO_PIPELINE_STAGE, required_stage);
+ bool already_posted = max_requested_pipeline_stage_ != NO_PIPELINE_STAGE;
+ max_requested_pipeline_stage_ =
+ std::max(max_requested_pipeline_stage_, required_stage);
+ if (already_posted)
+ return false;
+ channel_main_->SetNeedsCommitOnImpl();
+ return true;
+}
+
+bool ProxyMain::IsMainThread() const {
+ return task_runner_provider_->IsMainThread();
+}
+
+} // namespace cc
diff --git a/cc/trees/proxy_main.h b/cc/trees/proxy_main.h
index fbe191d..edc2a22 100644
--- a/cc/trees/proxy_main.h
+++ b/cc/trees/proxy_main.h
@@ -5,56 +5,155 @@
#ifndef CC_TREES_PROXY_MAIN_H_
#define CC_TREES_PROXY_MAIN_H_
-#include "base/memory/weak_ptr.h"
+#include "base/macros.h"
#include "cc/animation/animation_events.h"
#include "cc/base/cc_export.h"
#include "cc/debug/frame_timing_tracker.h"
+#include "cc/input/top_controls_state.h"
+#include "cc/output/output_surface.h"
#include "cc/output/renderer_capabilities.h"
+#include "cc/trees/channel_main.h"
+#include "cc/trees/proxy.h"
#include "cc/trees/proxy_common.h"
namespace cc {
-class ThreadedChannel;
-
-// TODO(khushalsagar): The main side of ThreadProxy. It is currently defined as
-// an interface with the implementation provided by ThreadProxy and will be
-// made an independent class.
-// The methods added to this interface should only use the MainThreadOnly or
-// BlockedMainThread variables from ThreadProxy.
-// See crbug/527200.
-class CC_EXPORT ProxyMain {
+class BeginFrameSource;
+class ChannelMain;
+class LayerTreeHost;
+
+// This class aggregates all interactions that the impl side of the compositor
+// needs to have with the main side.
+// The class is created and lives on the main thread.
+class CC_EXPORT ProxyMain : public Proxy {
public:
- // TODO(khushalsagar): Make this ChannelMain*. When ProxyMain and
- // ProxyImpl are split, ProxyImpl will be passed a reference to ChannelImpl
- // at creation. Right now we just set it directly from ThreadedChannel
- // when the impl side is initialized.
- virtual void SetChannel(scoped_ptr<ThreadedChannel> threaded_channel) = 0;
+ static scoped_ptr<ProxyMain> CreateThreaded(
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source);
- protected:
- virtual ~ProxyMain() {}
+ ~ProxyMain() override;
- private:
- friend class ThreadedChannel;
- // Callback for main side commands received from the Channel.
- virtual void DidCompleteSwapBuffers() = 0;
- virtual void SetRendererCapabilitiesMainCopy(
- const RendererCapabilities& capabilities) = 0;
- virtual void BeginMainFrameNotExpectedSoon() = 0;
- virtual void DidCommitAndDrawFrame() = 0;
- virtual void SetAnimationEvents(scoped_ptr<AnimationEventsVector> queue) = 0;
- virtual void DidLoseOutputSurface() = 0;
- virtual void RequestNewOutputSurface() = 0;
+ // Commits between the main and impl threads are processed through a pipeline
+ // with the following stages. For efficiency we can early out at any stage if
+ // we decide that no further processing is necessary.
+ enum CommitPipelineStage {
+ NO_PIPELINE_STAGE,
+ ANIMATE_PIPELINE_STAGE,
+ UPDATE_LAYERS_PIPELINE_STAGE,
+ COMMIT_PIPELINE_STAGE,
+ };
+
+ // Virtual for testing.
+ virtual void DidCompleteSwapBuffers();
+ virtual void SetRendererCapabilities(
+ const RendererCapabilities& capabilities);
+ virtual void BeginMainFrameNotExpectedSoon();
+ virtual void DidCommitAndDrawFrame();
+ virtual void SetAnimationEvents(scoped_ptr<AnimationEventsVector> queue);
+ virtual void DidLoseOutputSurface();
+ virtual void RequestNewOutputSurface();
virtual void DidInitializeOutputSurface(
bool success,
- const RendererCapabilities& capabilities) = 0;
- virtual void DidCompletePageScaleAnimation() = 0;
+ const RendererCapabilities& capabilities);
+ virtual void DidCompletePageScaleAnimation();
virtual void PostFrameTimingEventsOnMain(
scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
- scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) = 0;
+ scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events);
virtual void BeginMainFrame(
- scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) = 0;
+ scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state);
+
+ ChannelMain* channel_main() const { return channel_main_.get(); }
+ CommitPipelineStage max_requested_pipeline_stage() const {
+ return max_requested_pipeline_stage_;
+ }
+ CommitPipelineStage current_pipeline_stage() const {
+ return current_pipeline_stage_;
+ }
+ CommitPipelineStage final_pipeline_stage() const {
+ return final_pipeline_stage_;
+ }
+
+ protected:
+ ProxyMain(LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
+ private:
+ friend class ProxyMainForTest;
+
+ // Proxy implementation.
+ void FinishAllRendering() override;
+ bool IsStarted() const override;
+ bool CommitToActiveTree() const override;
+ void SetOutputSurface(OutputSurface* output_surface) override;
+ void SetVisible(bool visible) override;
+ void SetThrottleFrameProduction(bool throttle) override;
+ const RendererCapabilities& GetRendererCapabilities() const override;
+ void SetNeedsAnimate() override;
+ void SetNeedsUpdateLayers() override;
+ void SetNeedsCommit() override;
+ void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
+ void SetNextCommitWaitsForActivation() override;
+ void NotifyInputThrottledUntilCommit() override;
+ void SetDeferCommits(bool defer_commits) override;
+ bool CommitRequested() const override;
+ bool BeginMainFrameRequested() const override;
+ void MainThreadHasStoppedFlinging() override;
+ void Start() override;
+ void Stop() override;
+ bool SupportsImplScrolling() const override;
+ bool MainFrameWillHappenForTesting() override;
+ void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override;
+ void SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) override;
+ void ReleaseOutputSurface() override;
+ void UpdateTopControlsState(TopControlsState constraints,
+ TopControlsState current,
+ bool animate) override;
+
+ // This sets the channel used by ProxyMain to communicate with ProxyImpl.
+ void SetChannel(scoped_ptr<ChannelMain> channel_main);
+
+ // Returns |true| if the request was actually sent, |false| if one was
+ // already outstanding.
+ bool SendCommitRequestToImplThreadIfNeeded(
+ CommitPipelineStage required_stage);
+ bool IsMainThread() const;
+
+ LayerTreeHost* layer_tree_host_;
+
+ TaskRunnerProvider* task_runner_provider_;
+
+ const int layer_tree_host_id_;
+
+ // The furthest pipeline stage which has been requested for the next
+ // commit.
+ CommitPipelineStage max_requested_pipeline_stage_;
+ // The commit pipeline stage that is currently being processed.
+ CommitPipelineStage current_pipeline_stage_;
+ // The commit pipeline stage at which processing for the current commit
+ // will stop. Only valid while we are executing the pipeline (i.e.,
+ // |current_pipeline_stage| is set to a pipeline stage).
+ CommitPipelineStage final_pipeline_stage_;
+
+ bool commit_waits_for_activation_;
+
+ // Set when the Proxy is started using Proxy::Start() and reset when it is
+ // stopped using Proxy::Stop().
+ bool started_;
+
+ bool defer_commits_;
+
+ RendererCapabilities renderer_capabilities_;
+
+ // This holds a valid value only until ProxyImpl is created on the impl thread
+ // with InitializeImplOnImpl().
+ // TODO(khushalsagar): Remove the use of this temporary variable.
+ // See crbug/567930.
+ scoped_ptr<BeginFrameSource> external_begin_frame_source_;
+
+ scoped_ptr<ChannelMain> channel_main_;
- // TODO(khushalsagar): Rename as GetWeakPtr() once ThreadProxy is split.
- virtual base::WeakPtr<ProxyMain> GetMainWeakPtr() = 0;
+ DISALLOW_COPY_AND_ASSIGN(ProxyMain);
};
} // namespace cc
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
deleted file mode 100644
index 7e09d7a..0000000
--- a/cc/trees/thread_proxy.cc
+++ /dev/null
@@ -1,1190 +0,0 @@
-// Copyright 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/trees/thread_proxy.h"
-
-#include <algorithm>
-#include <string>
-
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/trace_event/trace_event_synthetic_delay.h"
-#include "cc/debug/benchmark_instrumentation.h"
-#include "cc/debug/devtools_instrumentation.h"
-#include "cc/input/input_handler.h"
-#include "cc/input/top_controls_manager.h"
-#include "cc/output/context_provider.h"
-#include "cc/output/output_surface.h"
-#include "cc/output/swap_promise.h"
-#include "cc/quads/draw_quad.h"
-#include "cc/scheduler/commit_earlyout_reason.h"
-#include "cc/scheduler/compositor_timing_history.h"
-#include "cc/scheduler/scheduler.h"
-#include "cc/trees/blocking_task_runner.h"
-#include "cc/trees/layer_tree_host.h"
-#include "cc/trees/layer_tree_impl.h"
-#include "cc/trees/scoped_abort_remaining_swap_promises.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-
-namespace cc {
-
-namespace {
-
-// Measured in seconds.
-const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
-
-unsigned int nextBeginFrameId = 0;
-
-} // namespace
-
-struct ThreadProxy::SchedulerStateRequest {
- CompletionEvent completion;
- scoped_ptr<base::Value> state;
-};
-
-scoped_ptr<Proxy> ThreadProxy::Create(
- LayerTreeHost* layer_tree_host,
- TaskRunnerProvider* task_runner_provider,
- scoped_ptr<BeginFrameSource> external_begin_frame_source) {
- return make_scoped_ptr(
- new ThreadProxy(layer_tree_host, task_runner_provider,
- std::move(external_begin_frame_source)));
-}
-
-ThreadProxy::ThreadProxy(
- LayerTreeHost* layer_tree_host,
- TaskRunnerProvider* task_runner_provider,
- scoped_ptr<BeginFrameSource> external_begin_frame_source)
- : task_runner_provider_(task_runner_provider),
- main_thread_only_vars_unsafe_(this, layer_tree_host),
- compositor_thread_vars_unsafe_(
- this,
- layer_tree_host->id(),
- layer_tree_host->rendering_stats_instrumentation(),
- std::move(external_begin_frame_source)) {
- TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
- DCHECK(task_runner_provider_);
- DCHECK(task_runner_provider_->IsMainThread());
- DCHECK(this->main().layer_tree_host);
- // TODO(khushalsagar): Move this to LayerTreeHost#InitializeThreaded once
- // ThreadProxy is split. LayerTreeHost creates the channel and passes it to
- // ProxyMain#SetChannel.
- SetChannel(ThreadedChannel::Create(this, task_runner_provider_));
-}
-
-ThreadProxy::MainThreadOnly::MainThreadOnly(ThreadProxy* proxy,
- LayerTreeHost* layer_tree_host)
- : layer_tree_host_id(layer_tree_host->id()),
- layer_tree_host(layer_tree_host),
- max_requested_pipeline_stage(NO_PIPELINE_STAGE),
- current_pipeline_stage(NO_PIPELINE_STAGE),
- final_pipeline_stage(NO_PIPELINE_STAGE),
- commit_waits_for_activation(false),
- started(false),
- prepare_tiles_pending(false),
- defer_commits(false),
- weak_factory(proxy) {}
-
-ThreadProxy::MainThreadOnly::~MainThreadOnly() {}
-
-ThreadProxy::BlockedMainCommitOnly::BlockedMainCommitOnly()
- : layer_tree_host(nullptr) {}
-
-ThreadProxy::BlockedMainCommitOnly::~BlockedMainCommitOnly() {}
-
-ThreadProxy::CompositorThreadOnly::CompositorThreadOnly(
- ThreadProxy* proxy,
- int layer_tree_host_id,
- RenderingStatsInstrumentation* rendering_stats_instrumentation,
- scoped_ptr<BeginFrameSource> external_begin_frame_source)
- : layer_tree_host_id(layer_tree_host_id),
- next_commit_waits_for_activation(false),
- commit_completion_event(nullptr),
- next_frame_is_newly_committed_frame(false),
- inside_draw(false),
- input_throttled_until_commit(false),
- smoothness_priority_expiration_notifier(
- proxy->task_runner_provider()
- ->ImplThreadTaskRunner(),
- base::Bind(&ThreadProxy::RenewTreePriority, base::Unretained(proxy)),
- base::TimeDelta::FromMilliseconds(
- kSmoothnessTakesPriorityExpirationDelay * 1000)),
- external_begin_frame_source(std::move(external_begin_frame_source)),
- rendering_stats_instrumentation(rendering_stats_instrumentation),
- weak_factory(proxy) {}
-
-ThreadProxy::CompositorThreadOnly::~CompositorThreadOnly() {}
-
-ThreadProxy::~ThreadProxy() {
- TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
- DCHECK(task_runner_provider_->IsMainThread());
- DCHECK(!main().started);
-}
-
-void ThreadProxy::SetChannel(scoped_ptr<ThreadedChannel> threaded_channel) {
- threaded_channel_ = std::move(threaded_channel);
- main().channel_main = threaded_channel_.get();
-}
-
-void ThreadProxy::FinishAllRendering() {
- DCHECK(task_runner_provider_->IsMainThread());
- DCHECK(!main().defer_commits);
-
- // Make sure all GL drawing is finished on the impl thread.
- DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
- CompletionEvent completion;
- main().channel_main->FinishAllRenderingOnImpl(&completion);
- completion.Wait();
-}
-
-bool ThreadProxy::IsStarted() const {
- DCHECK(task_runner_provider_->IsMainThread());
- return main().started;
-}
-
-bool ThreadProxy::CommitToActiveTree() const {
- // With ThreadProxy, we use a pending tree and activate it once it's ready to
- // draw to allow input to modify the active tree and draw during raster.
- return false;
-}
-
-void ThreadProxy::SetVisible(bool visible) {
- TRACE_EVENT1("cc", "ThreadProxy::SetVisible", "visible", visible);
- main().channel_main->SetVisibleOnImpl(visible);
-}
-
-void ThreadProxy::SetVisibleOnImpl(bool visible) {
- TRACE_EVENT1("cc", "ThreadProxy::SetVisibleOnImplThread", "visible", visible);
- impl().layer_tree_host_impl->SetVisible(visible);
- impl().scheduler->SetVisible(visible);
-}
-
-void ThreadProxy::SetThrottleFrameProduction(bool throttle) {
- TRACE_EVENT1("cc", "ThreadProxy::SetThrottleFrameProduction", "throttle",
- throttle);
- main().channel_main->SetThrottleFrameProductionOnImpl(throttle);
-}
-
-void ThreadProxy::SetThrottleFrameProductionOnImpl(bool throttle) {
- TRACE_EVENT1("cc", "ThreadProxy::SetThrottleFrameProductionOnImplThread",
- "throttle", throttle);
- impl().scheduler->SetThrottleFrameProduction(throttle);
-}
-
-void ThreadProxy::DidLoseOutputSurface() {
- TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurface");
- DCHECK(task_runner_provider_->IsMainThread());
- main().layer_tree_host->DidLoseOutputSurface();
-}
-
-void ThreadProxy::RequestNewOutputSurface() {
- DCHECK(task_runner_provider_->IsMainThread());
- main().layer_tree_host->RequestNewOutputSurface();
-}
-
-void ThreadProxy::SetOutputSurface(OutputSurface* output_surface) {
- main().channel_main->InitializeOutputSurfaceOnImpl(output_surface);
-}
-
-void ThreadProxy::ReleaseOutputSurface() {
- DCHECK(task_runner_provider_->IsMainThread());
- DCHECK(main().layer_tree_host->output_surface_lost());
-
- DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
- CompletionEvent completion;
- main().channel_main->ReleaseOutputSurfaceOnImpl(&completion);
- completion.Wait();
-}
-
-void ThreadProxy::DidInitializeOutputSurface(
- bool success,
- const RendererCapabilities& capabilities) {
- TRACE_EVENT0("cc", "ThreadProxy::DidInitializeOutputSurface");
- DCHECK(task_runner_provider_->IsMainThread());
-
- if (!success) {
- main().layer_tree_host->DidFailToInitializeOutputSurface();
- return;
- }
- main().renderer_capabilities_main_thread_copy = capabilities;
- main().layer_tree_host->DidInitializeOutputSurface();
-}
-
-void ThreadProxy::SetRendererCapabilitiesMainCopy(
- const RendererCapabilities& capabilities) {
- main().renderer_capabilities_main_thread_copy = capabilities;
-}
-
-bool ThreadProxy::SendCommitRequestToImplThreadIfNeeded(
- CommitPipelineStage required_stage) {
- DCHECK(task_runner_provider_->IsMainThread());
- DCHECK_NE(NO_PIPELINE_STAGE, required_stage);
- bool already_posted =
- main().max_requested_pipeline_stage != NO_PIPELINE_STAGE;
- main().max_requested_pipeline_stage =
- std::max(main().max_requested_pipeline_stage, required_stage);
- if (already_posted)
- return false;
- main().channel_main->SetNeedsCommitOnImpl();
- return true;
-}
-
-void ThreadProxy::SetNeedsCommitOnImpl() {
- SetNeedsCommitOnImplThread();
-}
-
-void ThreadProxy::DidCompletePageScaleAnimation() {
- DCHECK(task_runner_provider_->IsMainThread());
- main().layer_tree_host->DidCompletePageScaleAnimation();
-}
-
-const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const {
- DCHECK(task_runner_provider_->IsMainThread());
- DCHECK(!main().layer_tree_host->output_surface_lost());
- return main().renderer_capabilities_main_thread_copy;
-}
-
-void ThreadProxy::SetNeedsAnimate() {
- DCHECK(task_runner_provider_->IsMainThread());
- if (SendCommitRequestToImplThreadIfNeeded(ANIMATE_PIPELINE_STAGE)) {
- TRACE_EVENT_INSTANT0("cc", "ThreadProxy::SetNeedsAnimate",
- TRACE_EVENT_SCOPE_THREAD);
- }
-}
-
-void ThreadProxy::SetNeedsUpdateLayers() {
- DCHECK(task_runner_provider_->IsMainThread());
- // If we are currently animating, make sure we also update the layers.
- if (main().current_pipeline_stage == ANIMATE_PIPELINE_STAGE) {
- main().final_pipeline_stage =
- std::max(main().final_pipeline_stage, UPDATE_LAYERS_PIPELINE_STAGE);
- return;
- }
- if (SendCommitRequestToImplThreadIfNeeded(UPDATE_LAYERS_PIPELINE_STAGE)) {
- TRACE_EVENT_INSTANT0("cc", "ThreadProxy::SetNeedsUpdateLayers",
- TRACE_EVENT_SCOPE_THREAD);
- }
-}
-
-void ThreadProxy::SetNeedsCommit() {
- DCHECK(task_runner_provider_->IsMainThread());
- // If we are currently animating, make sure we don't skip the commit. Note
- // that requesting a commit during the layer update stage means we need to
- // schedule another full commit.
- if (main().current_pipeline_stage == ANIMATE_PIPELINE_STAGE) {
- main().final_pipeline_stage =
- std::max(main().final_pipeline_stage, COMMIT_PIPELINE_STAGE);
- return;
- }
- if (SendCommitRequestToImplThreadIfNeeded(COMMIT_PIPELINE_STAGE)) {
- TRACE_EVENT_INSTANT0("cc", "ThreadProxy::SetNeedsCommit",
- TRACE_EVENT_SCOPE_THREAD);
- }
-}
-
-void ThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
- DCHECK(task_runner_provider_->IsImplThread());
- impl().channel_impl->SetRendererCapabilitiesMainCopy(
- impl()
- .layer_tree_host_impl->GetRendererCapabilities()
- .MainThreadCapabilities());
-}
-
-void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
- TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
- DCHECK(task_runner_provider_->IsImplThread());
- impl().channel_impl->DidLoseOutputSurface();
- impl().scheduler->DidLoseOutputSurface();
-}
-
-void ThreadProxy::CommitVSyncParameters(base::TimeTicks timebase,
- base::TimeDelta interval) {
- impl().scheduler->CommitVSyncParameters(timebase, interval);
-}
-
-void ThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
- impl().scheduler->SetEstimatedParentDrawTime(draw_time);
-}
-
-void ThreadProxy::DidSwapBuffersOnImplThread() {
- impl().scheduler->DidSwapBuffers();
-}
-
-void ThreadProxy::DidSwapBuffersCompleteOnImplThread() {
- TRACE_EVENT0("cc,benchmark",
- "ThreadProxy::DidSwapBuffersCompleteOnImplThread");
- DCHECK(task_runner_provider_->IsImplThread());
- impl().scheduler->DidSwapBuffersComplete();
- impl().channel_impl->DidCompleteSwapBuffers();
-}
-
-void ThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
- impl().layer_tree_host_impl->WillBeginImplFrame(args);
- if (impl().last_processed_begin_main_frame_args.IsValid()) {
- // Last processed begin main frame args records the frame args that we sent
- // to the main thread for the last frame that we've processed. If that is
- // set, that means the current frame is one past the frame in which we've
- // finished the processing.
- impl().layer_tree_host_impl->RecordMainFrameTiming(
- impl().last_processed_begin_main_frame_args, args);
- impl().last_processed_begin_main_frame_args = BeginFrameArgs();
- }
-}
-
-void ThreadProxy::OnResourcelessSoftareDrawStateChanged(
- bool resourceless_draw) {
- DCHECK(task_runner_provider_->IsImplThread());
- impl().scheduler->SetResourcelessSoftareDraw(resourceless_draw);
-}
-
-void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
- TRACE_EVENT1(
- "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
- DCHECK(task_runner_provider_->IsImplThread());
- impl().scheduler->SetCanDraw(can_draw);
-}
-
-void ThreadProxy::NotifyReadyToActivate() {
- TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate");
- impl().scheduler->NotifyReadyToActivate();
-}
-
-void ThreadProxy::NotifyReadyToDraw() {
- TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToDraw");
- impl().scheduler->NotifyReadyToDraw();
-}
-
-void ThreadProxy::SetNeedsCommitOnImplThread() {
- TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
- DCHECK(task_runner_provider_->IsImplThread());
- impl().scheduler->SetNeedsBeginMainFrame();
-}
-
-void ThreadProxy::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
- TRACE_EVENT1("cc", "ThreadProxy::SetVideoNeedsBeginFrames",
- "needs_begin_frames", needs_begin_frames);
- DCHECK(task_runner_provider_->IsImplThread());
- // In tests the layer tree is destroyed after the scheduler is.
- if (impl().scheduler)
- impl().scheduler->SetVideoNeedsBeginFrames(needs_begin_frames);
-}
-
-void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
- scoped_ptr<AnimationEventsVector> events) {
- TRACE_EVENT0("cc",
- "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
- DCHECK(task_runner_provider_->IsImplThread());
- impl().channel_impl->SetAnimationEvents(std::move(events));
-}
-
-bool ThreadProxy::IsInsideDraw() { return impl().inside_draw; }
-
-void ThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
- TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
- DCHECK(task_runner_provider_->IsMainThread());
- main().channel_main->SetNeedsRedrawOnImpl(damage_rect);
-}
-
-void ThreadProxy::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
- DCHECK(task_runner_provider_->IsImplThread());
- SetNeedsRedrawRectOnImplThread(damage_rect);
-}
-
-void ThreadProxy::SetNextCommitWaitsForActivation() {
- DCHECK(task_runner_provider_->IsMainThread());
- main().commit_waits_for_activation = true;
-}
-
-void ThreadProxy::SetDeferCommits(bool defer_commits) {
- DCHECK(task_runner_provider_->IsMainThread());
- 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
- TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
-
- main().channel_main->SetDeferCommitsOnImpl(defer_commits);
-}
-
-void ThreadProxy::SetDeferCommitsOnImpl(bool defer_commits) const {
- DCHECK(task_runner_provider_->IsImplThread());
- impl().scheduler->SetDeferCommits(defer_commits);
-}
-
-bool ThreadProxy::CommitRequested() const {
- DCHECK(task_runner_provider_->IsMainThread());
- // TODO(skyostil): Split this into something like CommitRequested() and
- // CommitInProgress().
- return main().current_pipeline_stage != NO_PIPELINE_STAGE ||
- main().max_requested_pipeline_stage >= COMMIT_PIPELINE_STAGE;
-}
-
-bool ThreadProxy::BeginMainFrameRequested() const {
- DCHECK(task_runner_provider_->IsMainThread());
- return main().max_requested_pipeline_stage != NO_PIPELINE_STAGE;
-}
-
-void ThreadProxy::SetNeedsRedrawOnImplThread() {
- TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
- DCHECK(task_runner_provider_->IsImplThread());
- impl().scheduler->SetNeedsRedraw();
-}
-
-void ThreadProxy::SetNeedsOneBeginImplFrameOnImplThread() {
- TRACE_EVENT0("cc", "ThreadProxy::SetNeedsOneBeginImplFrameOnImplThread");
- DCHECK(task_runner_provider_->IsImplThread());
- impl().scheduler->SetNeedsOneBeginImplFrame();
-}
-
-void ThreadProxy::SetNeedsPrepareTilesOnImplThread() {
- DCHECK(task_runner_provider_->IsImplThread());
- impl().scheduler->SetNeedsPrepareTiles();
-}
-
-void ThreadProxy::SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) {
- DCHECK(task_runner_provider_->IsImplThread());
- impl().layer_tree_host_impl->SetViewportDamage(damage_rect);
- SetNeedsRedrawOnImplThread();
-}
-
-void ThreadProxy::MainThreadHasStoppedFlinging() {
- DCHECK(task_runner_provider_->IsMainThread());
- main().channel_main->MainThreadHasStoppedFlingingOnImpl();
-}
-
-void ThreadProxy::MainThreadHasStoppedFlingingOnImpl() {
- DCHECK(task_runner_provider_->IsImplThread());
- impl().layer_tree_host_impl->MainThreadHasStoppedFlinging();
-}
-
-void ThreadProxy::NotifyInputThrottledUntilCommit() {
- DCHECK(task_runner_provider_->IsMainThread());
- main().channel_main->SetInputThrottledUntilCommitOnImpl(true);
-}
-
-void ThreadProxy::SetInputThrottledUntilCommitOnImpl(bool is_throttled) {
- DCHECK(task_runner_provider_->IsImplThread());
- if (is_throttled == impl().input_throttled_until_commit)
- return;
- impl().input_throttled_until_commit = is_throttled;
- RenewTreePriority();
-}
-
-ThreadProxy::MainThreadOnly& ThreadProxy::main() {
- DCHECK(task_runner_provider_->IsMainThread());
- return main_thread_only_vars_unsafe_;
-}
-const ThreadProxy::MainThreadOnly& ThreadProxy::main() const {
- DCHECK(task_runner_provider_->IsMainThread());
- return main_thread_only_vars_unsafe_;
-}
-
-ThreadProxy::BlockedMainCommitOnly& ThreadProxy::blocked_main_commit() {
- DCHECK(impl().commit_completion_event);
- DCHECK(task_runner_provider_->IsMainThreadBlocked());
- return main_thread_blocked_commit_vars_unsafe_;
-}
-
-ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() {
- DCHECK(task_runner_provider_->IsImplThread());
- return compositor_thread_vars_unsafe_;
-}
-
-const ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() const {
- DCHECK(task_runner_provider_->IsImplThread());
- return compositor_thread_vars_unsafe_;
-}
-
-void ThreadProxy::Start() {
- DCHECK(task_runner_provider_->IsMainThread());
- DCHECK(task_runner_provider_->HasImplThread());
-
- // Create LayerTreeHostImpl.
- DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
- CompletionEvent completion;
- main().channel_main->InitializeImplOnImpl(&completion,
- main().layer_tree_host);
- completion.Wait();
-
- main_thread_weak_ptr_ = main().weak_factory.GetWeakPtr();
-
- main().started = true;
-}
-
-void ThreadProxy::Stop() {
- TRACE_EVENT0("cc", "ThreadProxy::Stop");
- DCHECK(task_runner_provider_->IsMainThread());
- DCHECK(main().started);
-
- // Synchronously finishes pending GL operations and deletes the impl.
- // The two steps are done as separate post tasks, so that tasks posted
- // by the GL implementation due to the Finish can be executed by the
- // renderer before shutting it down.
- {
- DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
- CompletionEvent completion;
- main().channel_main->FinishGLOnImpl(&completion);
- completion.Wait();
- }
- {
- DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
-
- CompletionEvent completion;
- main().channel_main->LayerTreeHostClosedOnImpl(&completion);
- completion.Wait();
- }
-
- main().weak_factory.InvalidateWeakPtrs();
- main().layer_tree_host = nullptr;
- main().started = false;
-}
-
-bool ThreadProxy::SupportsImplScrolling() const {
- return true;
-}
-
-void ThreadProxy::FinishAllRenderingOnImpl(CompletionEvent* completion) {
- TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
- DCHECK(task_runner_provider_->IsImplThread());
- impl().layer_tree_host_impl->FinishAllRendering();
- completion->Signal();
-}
-
-void ThreadProxy::ScheduledActionSendBeginMainFrame(
- const BeginFrameArgs& args) {
- unsigned int begin_frame_id = nextBeginFrameId++;
- benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
- benchmark_instrumentation::kSendBeginFrame, begin_frame_id);
- scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state(
- new BeginMainFrameAndCommitState);
- begin_main_frame_state->begin_frame_id = begin_frame_id;
- begin_main_frame_state->begin_frame_args = args;
- begin_main_frame_state->scroll_info =
- impl().layer_tree_host_impl->ProcessScrollDeltas();
- begin_main_frame_state->memory_allocation_limit_bytes =
- impl().layer_tree_host_impl->memory_allocation_limit_bytes();
- begin_main_frame_state->evicted_ui_resources =
- impl().layer_tree_host_impl->EvictedUIResourcesExist();
- // TODO(vmpstr): This needs to be fixed if
- // main_frame_before_activation_enabled is set, since we might run this code
- // twice before recording a duration. crbug.com/469824
- impl().last_begin_main_frame_args = begin_main_frame_state->begin_frame_args;
- impl().channel_impl->BeginMainFrame(std::move(begin_main_frame_state));
- devtools_instrumentation::DidRequestMainThreadFrame(
- impl().layer_tree_host_id);
-}
-
-void ThreadProxy::SendBeginMainFrameNotExpectedSoon() {
- impl().channel_impl->BeginMainFrameNotExpectedSoon();
-}
-
-void ThreadProxy::BeginMainFrame(
- scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
- benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
- benchmark_instrumentation::kDoBeginFrame,
- begin_main_frame_state->begin_frame_id);
-
- base::TimeTicks begin_main_frame_start_time = base::TimeTicks::Now();
-
- TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame");
- DCHECK(task_runner_provider_->IsMainThread());
- DCHECK_EQ(NO_PIPELINE_STAGE, main().current_pipeline_stage);
-
- if (main().defer_commits) {
- TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
- TRACE_EVENT_SCOPE_THREAD);
- main().channel_main->BeginMainFrameAbortedOnImpl(
- CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT,
- begin_main_frame_start_time);
- return;
- }
-
- // If the commit finishes, LayerTreeHost will transfer its swap promises to
- // LayerTreeImpl. The destructor of ScopedSwapPromiseChecker aborts the
- // remaining swap promises.
- ScopedAbortRemainingSwapPromises swap_promise_checker(main().layer_tree_host);
-
- main().final_pipeline_stage = main().max_requested_pipeline_stage;
- main().max_requested_pipeline_stage = NO_PIPELINE_STAGE;
-
- if (!main().layer_tree_host->visible()) {
- TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
- main().channel_main->BeginMainFrameAbortedOnImpl(
- CommitEarlyOutReason::ABORTED_NOT_VISIBLE, begin_main_frame_start_time);
- return;
- }
-
- if (main().layer_tree_host->output_surface_lost()) {
- TRACE_EVENT_INSTANT0(
- "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
- main().channel_main->BeginMainFrameAbortedOnImpl(
- CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST,
- begin_main_frame_start_time);
- return;
- }
-
- main().current_pipeline_stage = ANIMATE_PIPELINE_STAGE;
-
- main().layer_tree_host->ApplyScrollAndScale(
- begin_main_frame_state->scroll_info.get());
-
- main().layer_tree_host->WillBeginMainFrame();
-
- main().layer_tree_host->BeginMainFrame(
- begin_main_frame_state->begin_frame_args);
- main().layer_tree_host->AnimateLayers(
- begin_main_frame_state->begin_frame_args.frame_time);
-
- // Recreate all UI resources if there were evicted UI resources when the impl
- // thread initiated the commit.
- if (begin_main_frame_state->evicted_ui_resources)
- main().layer_tree_host->RecreateUIResources();
-
- main().layer_tree_host->RequestMainFrameUpdate();
- TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
-
- bool can_cancel_this_commit =
- main().final_pipeline_stage < COMMIT_PIPELINE_STAGE &&
- !begin_main_frame_state->evicted_ui_resources;
-
- main().current_pipeline_stage = UPDATE_LAYERS_PIPELINE_STAGE;
- bool should_update_layers =
- main().final_pipeline_stage >= UPDATE_LAYERS_PIPELINE_STAGE;
- bool updated = should_update_layers && main().layer_tree_host->UpdateLayers();
-
- main().layer_tree_host->WillCommit();
- devtools_instrumentation::ScopedCommitTrace commit_task(
- main().layer_tree_host->id());
-
- main().current_pipeline_stage = COMMIT_PIPELINE_STAGE;
- if (!updated && can_cancel_this_commit) {
- TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD);
- main().channel_main->BeginMainFrameAbortedOnImpl(
- CommitEarlyOutReason::FINISHED_NO_UPDATES, begin_main_frame_start_time);
-
- // Although the commit is internally aborted, this is because it has been
- // detected to be a no-op. From the perspective of an embedder, this commit
- // went through, and input should no longer be throttled, etc.
- main().current_pipeline_stage = NO_PIPELINE_STAGE;
- main().layer_tree_host->CommitComplete();
- main().layer_tree_host->DidBeginMainFrame();
- main().layer_tree_host->BreakSwapPromises(SwapPromise::COMMIT_NO_UPDATE);
- return;
- }
-
- // Notify the impl thread that the main thread is ready to commit. This will
- // begin the commit process, which is blocking from the main thread's
- // point of view, but asynchronously performed on the impl thread,
- // coordinated by the Scheduler.
- {
- TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame::commit");
-
- DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
-
- // This CapturePostTasks should be destroyed before CommitComplete() is
- // called since that goes out to the embedder, and we want the embedder
- // to receive its callbacks before that.
- BlockingTaskRunner::CapturePostTasks blocked(
- task_runner_provider_->blocking_main_thread_task_runner());
-
- CompletionEvent completion;
- main().channel_main->StartCommitOnImpl(&completion, main().layer_tree_host,
- begin_main_frame_start_time,
- main().commit_waits_for_activation);
- completion.Wait();
- main().commit_waits_for_activation = false;
- }
-
- main().current_pipeline_stage = NO_PIPELINE_STAGE;
- main().layer_tree_host->CommitComplete();
- main().layer_tree_host->DidBeginMainFrame();
-}
-
-void ThreadProxy::BeginMainFrameNotExpectedSoon() {
- TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrameNotExpectedSoon");
- DCHECK(task_runner_provider_->IsMainThread());
- main().layer_tree_host->BeginMainFrameNotExpectedSoon();
-}
-
-void ThreadProxy::StartCommitOnImpl(CompletionEvent* completion,
- LayerTreeHost* layer_tree_host,
- base::TimeTicks main_thread_start_time,
- bool hold_commit_for_activation) {
- TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread");
- DCHECK(!impl().commit_completion_event);
- DCHECK(task_runner_provider_->IsImplThread() &&
- task_runner_provider_->IsMainThreadBlocked());
- DCHECK(impl().scheduler);
- DCHECK(impl().scheduler->CommitPending());
-
- if (hold_commit_for_activation) {
- // This commit may be aborted. Store the value for
- // hold_commit_for_activation so that whenever the next commit is started,
- // the main thread will be unblocked only after pending tree activation.
- impl().next_commit_waits_for_activation = hold_commit_for_activation;
- }
-
- if (!impl().layer_tree_host_impl) {
- TRACE_EVENT_INSTANT0(
- "cc", "EarlyOut_NoLayerTree", TRACE_EVENT_SCOPE_THREAD);
- completion->Signal();
- return;
- }
-
- // Ideally, we should inform to impl thread when BeginMainFrame is started.
- // But, we can avoid a PostTask in here.
- impl().scheduler->NotifyBeginMainFrameStarted(main_thread_start_time);
- impl().commit_completion_event = completion;
- DCHECK(!blocked_main_commit().layer_tree_host);
- blocked_main_commit().layer_tree_host = layer_tree_host;
- impl().scheduler->NotifyReadyToCommit();
-}
-
-void ThreadProxy::BeginMainFrameAbortedOnImpl(
- CommitEarlyOutReason reason,
- base::TimeTicks main_thread_start_time) {
- TRACE_EVENT1("cc", "ThreadProxy::BeginMainFrameAbortedOnImplThread", "reason",
- CommitEarlyOutReasonToString(reason));
- DCHECK(task_runner_provider_->IsImplThread());
- DCHECK(impl().scheduler);
- DCHECK(impl().scheduler->CommitPending());
- DCHECK(!impl().layer_tree_host_impl->pending_tree());
-
- if (CommitEarlyOutHandledCommit(reason)) {
- SetInputThrottledUntilCommitOnImpl(false);
- impl().last_processed_begin_main_frame_args =
- impl().last_begin_main_frame_args;
- }
- impl().layer_tree_host_impl->BeginMainFrameAborted(reason);
- impl().scheduler->NotifyBeginMainFrameStarted(main_thread_start_time);
- impl().scheduler->BeginMainFrameAborted(reason);
-}
-
-void ThreadProxy::ScheduledActionCommit() {
- TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
- DCHECK(task_runner_provider_->IsImplThread());
- DCHECK(task_runner_provider_->IsMainThreadBlocked());
- DCHECK(impl().commit_completion_event);
- DCHECK(blocked_main_commit().layer_tree_host);
-
- impl().layer_tree_host_impl->BeginCommit();
- blocked_main_commit().layer_tree_host->FinishCommitOnImplThread(
- impl().layer_tree_host_impl.get());
-
- // Remove the LayerTreeHost reference before the completion event is signaled
- // and cleared. This is necessary since blocked_main_commit() allows access
- // only while we have the completion event to ensure the main thread is
- // blocked for a commit.
- blocked_main_commit().layer_tree_host = nullptr;
-
- if (impl().next_commit_waits_for_activation) {
- // For some layer types in impl-side painting, the commit is held until
- // the sync tree is activated. It's also possible that the
- // sync tree has already activated if there was no work to be done.
- TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
- } else {
- impl().commit_completion_event->Signal();
- impl().commit_completion_event = nullptr;
- }
-
- impl().scheduler->DidCommit();
-
- // Delay this step until afer the main thread has been released as it's
- // often a good bit of work to update the tree and prepare the new frame.
- impl().layer_tree_host_impl->CommitComplete();
-
- SetInputThrottledUntilCommitOnImpl(false);
-
- impl().next_frame_is_newly_committed_frame = true;
-}
-
-void ThreadProxy::ScheduledActionActivateSyncTree() {
- TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivateSyncTree");
- DCHECK(task_runner_provider_->IsImplThread());
- impl().layer_tree_host_impl->ActivateSyncTree();
-}
-
-void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
- TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginOutputSurfaceCreation");
- DCHECK(task_runner_provider_->IsImplThread());
- impl().channel_impl->RequestNewOutputSurface();
-}
-
-DrawResult ThreadProxy::DrawSwapInternal(bool forced_draw) {
- TRACE_EVENT_SYNTHETIC_DELAY("cc.DrawAndSwap");
- DrawResult result;
-
- DCHECK(task_runner_provider_->IsImplThread());
- DCHECK(impl().layer_tree_host_impl.get());
-
- base::AutoReset<bool> mark_inside(&impl().inside_draw, true);
-
- if (impl().layer_tree_host_impl->pending_tree()) {
- bool update_lcd_text = false;
- impl().layer_tree_host_impl->pending_tree()->UpdateDrawProperties(
- update_lcd_text);
- }
-
- // This method is called on a forced draw, regardless of whether we are able
- // to produce a frame, as the calling site on main thread is blocked until its
- // request completes, and we signal completion here. If CanDraw() is false, we
- // will indicate success=false to the caller, but we must still signal
- // completion to avoid deadlock.
-
- // We guard PrepareToDraw() with CanDraw() because it always returns a valid
- // frame, so can only be used when such a frame is possible. Since
- // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
- // CanDraw() as well.
-
- LayerTreeHostImpl::FrameData frame;
- bool draw_frame = false;
-
- if (impl().layer_tree_host_impl->CanDraw()) {
- result = impl().layer_tree_host_impl->PrepareToDraw(&frame);
- draw_frame = forced_draw || result == DRAW_SUCCESS;
- } else {
- result = DRAW_ABORTED_CANT_DRAW;
- }
-
- if (draw_frame) {
- impl().layer_tree_host_impl->DrawLayers(&frame);
- result = DRAW_SUCCESS;
- } else {
- DCHECK_NE(DRAW_SUCCESS, result);
- }
- impl().layer_tree_host_impl->DidDrawAllLayers(frame);
-
- bool start_ready_animations = draw_frame;
- impl().layer_tree_host_impl->UpdateAnimationState(start_ready_animations);
-
- if (draw_frame)
- impl().layer_tree_host_impl->SwapBuffers(frame);
-
- // Tell the main thread that the the newly-commited frame was drawn.
- if (impl().next_frame_is_newly_committed_frame) {
- impl().next_frame_is_newly_committed_frame = false;
- impl().channel_impl->DidCommitAndDrawFrame();
- }
-
- DCHECK_NE(INVALID_RESULT, result);
- return result;
-}
-
-void ThreadProxy::ScheduledActionPrepareTiles() {
- TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionPrepareTiles");
- impl().layer_tree_host_impl->PrepareTiles();
-}
-
-DrawResult ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
- TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
-
- // SchedulerStateMachine::DidDrawIfPossibleCompleted isn't set up to
- // handle DRAW_ABORTED_CANT_DRAW. Moreover, the scheduler should
- // never generate this call when it can't draw.
- DCHECK(impl().layer_tree_host_impl->CanDraw());
-
- bool forced_draw = false;
- return DrawSwapInternal(forced_draw);
-}
-
-DrawResult ThreadProxy::ScheduledActionDrawAndSwapForced() {
- TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwapForced");
- bool forced_draw = true;
- return DrawSwapInternal(forced_draw);
-}
-
-void ThreadProxy::ScheduledActionInvalidateOutputSurface() {
- TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionInvalidateOutputSurface");
- DCHECK(impl().layer_tree_host_impl->output_surface());
- impl().layer_tree_host_impl->output_surface()->Invalidate();
-}
-
-void ThreadProxy::DidFinishImplFrame() {
- impl().layer_tree_host_impl->DidFinishImplFrame();
-}
-
-void ThreadProxy::SendBeginFramesToChildren(const BeginFrameArgs& args) {
- NOTREACHED() << "Only used by SingleThreadProxy";
-}
-
-void ThreadProxy::SetAuthoritativeVSyncInterval(
- const base::TimeDelta& interval) {
- NOTREACHED() << "Only used by SingleThreadProxy";
-}
-
-void ThreadProxy::DidCommitAndDrawFrame() {
- DCHECK(task_runner_provider_->IsMainThread());
- main().layer_tree_host->DidCommitAndDrawFrame();
-}
-
-void ThreadProxy::DidCompleteSwapBuffers() {
- DCHECK(task_runner_provider_->IsMainThread());
- main().layer_tree_host->DidCompleteSwapBuffers();
-}
-
-void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
- TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
- DCHECK(task_runner_provider_->IsMainThread());
- main().layer_tree_host->SetAnimationEvents(std::move(events));
-}
-
-void ThreadProxy::InitializeImplOnImpl(CompletionEvent* completion,
- LayerTreeHost* layer_tree_host) {
- TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
- DCHECK(task_runner_provider_->IsImplThread());
- DCHECK(task_runner_provider_->IsMainThreadBlocked());
- DCHECK(layer_tree_host);
-
- // TODO(khushalsagar): ThreadedChannel will create ProxyImpl here and pass a
- // reference to itself.
- impl().channel_impl = threaded_channel_.get();
-
- impl().layer_tree_host_impl = layer_tree_host->CreateLayerTreeHostImpl(this);
-
- SchedulerSettings scheduler_settings(
- layer_tree_host->settings().ToSchedulerSettings());
-
- scoped_ptr<CompositorTimingHistory> compositor_timing_history(
- new CompositorTimingHistory(CompositorTimingHistory::RENDERER_UMA,
- impl().rendering_stats_instrumentation));
-
- impl().scheduler =
- Scheduler::Create(this, scheduler_settings, impl().layer_tree_host_id,
- task_runner_provider_->ImplThreadTaskRunner(),
- impl().external_begin_frame_source.get(),
- std::move(compositor_timing_history));
-
- DCHECK_EQ(impl().scheduler->visible(),
- impl().layer_tree_host_impl->visible());
- impl_thread_weak_ptr_ = impl().weak_factory.GetWeakPtr();
- completion->Signal();
-}
-
-void ThreadProxy::InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) {
- TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
- DCHECK(task_runner_provider_->IsImplThread());
-
- LayerTreeHostImpl* host_impl = impl().layer_tree_host_impl.get();
- bool success = host_impl->InitializeRenderer(output_surface);
- RendererCapabilities capabilities;
- if (success) {
- capabilities =
- host_impl->GetRendererCapabilities().MainThreadCapabilities();
- }
-
- impl().channel_impl->DidInitializeOutputSurface(success, capabilities);
-
- if (success)
- impl().scheduler->DidCreateAndInitializeOutputSurface();
-}
-
-void ThreadProxy::ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) {
- DCHECK(task_runner_provider_->IsImplThread());
-
- // Unlike DidLoseOutputSurfaceOnImplThread, we don't need to call
- // LayerTreeHost::DidLoseOutputSurface since it already knows.
- impl().scheduler->DidLoseOutputSurface();
- impl().layer_tree_host_impl->ReleaseOutputSurface();
- completion->Signal();
-}
-
-void ThreadProxy::FinishGLOnImpl(CompletionEvent* completion) {
- TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread");
- DCHECK(task_runner_provider_->IsImplThread());
- if (impl().layer_tree_host_impl->output_surface()) {
- ContextProvider* context_provider =
- impl().layer_tree_host_impl->output_surface()->context_provider();
- if (context_provider)
- context_provider->ContextGL()->Finish();
- }
- completion->Signal();
-}
-
-void ThreadProxy::LayerTreeHostClosedOnImpl(CompletionEvent* completion) {
- TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
- DCHECK(task_runner_provider_->IsImplThread());
- DCHECK(task_runner_provider_->IsMainThreadBlocked());
- impl().scheduler = nullptr;
- impl().external_begin_frame_source = nullptr;
- impl().layer_tree_host_impl = nullptr;
- impl().weak_factory.InvalidateWeakPtrs();
- // We need to explicitly shutdown the notifier to destroy any weakptrs it is
- // holding while still on the compositor thread. This also ensures any
- // callbacks holding a ThreadProxy pointer are cancelled.
- impl().smoothness_priority_expiration_notifier.Shutdown();
- completion->Signal();
-}
-
-bool ThreadProxy::MainFrameWillHappenForTesting() {
- DCHECK(task_runner_provider_->IsMainThread());
- bool main_frame_will_happen = false;
- {
- DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
- CompletionEvent completion;
- main().channel_main->MainFrameWillHappenOnImplForTesting(
- &completion, &main_frame_will_happen);
- completion.Wait();
- }
- return main_frame_will_happen;
-}
-
-void ThreadProxy::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
- NOTREACHED() << "Only used by SingleThreadProxy";
-}
-
-void ThreadProxy::MainFrameWillHappenOnImplForTesting(
- CompletionEvent* completion,
- bool* main_frame_will_happen) {
- DCHECK(task_runner_provider_->IsImplThread());
- if (impl().layer_tree_host_impl->output_surface()) {
- *main_frame_will_happen = impl().scheduler->MainFrameForTestingWillHappen();
- } else {
- *main_frame_will_happen = false;
- }
- completion->Signal();
-}
-
-void ThreadProxy::RenewTreePriority() {
- DCHECK(task_runner_provider_->IsImplThread());
- bool smoothness_takes_priority =
- impl().layer_tree_host_impl->pinch_gesture_active() ||
- impl().layer_tree_host_impl->page_scale_animation_active() ||
- impl().layer_tree_host_impl->IsActivelyScrolling();
-
- // Schedule expiration if smoothness currently takes priority.
- if (smoothness_takes_priority)
- impl().smoothness_priority_expiration_notifier.Schedule();
-
- // We use the same priority for both trees by default.
- TreePriority tree_priority = SAME_PRIORITY_FOR_BOTH_TREES;
-
- // Smoothness takes priority if we have an expiration for it scheduled.
- if (impl().smoothness_priority_expiration_notifier.HasPendingNotification())
- tree_priority = SMOOTHNESS_TAKES_PRIORITY;
-
- // New content always takes priority when there is an invalid viewport size or
- // ui resources have been evicted.
- if (impl().layer_tree_host_impl->active_tree()->ViewportSizeInvalid() ||
- impl().layer_tree_host_impl->EvictedUIResourcesExist() ||
- impl().input_throttled_until_commit) {
- // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active
- // tree might be freed. We need to set RequiresHighResToDraw to ensure that
- // high res tiles will be required to activate pending tree.
- impl().layer_tree_host_impl->SetRequiresHighResToDraw();
- tree_priority = NEW_CONTENT_TAKES_PRIORITY;
- }
-
- impl().layer_tree_host_impl->SetTreePriority(tree_priority);
-
- // Only put the scheduler in impl latency prioritization mode if we don't
- // have a scroll listener. This gives the scroll listener a better chance of
- // handling scroll updates within the same frame. The tree itself is still
- // kept in prefer smoothness mode to allow checkerboarding.
- ScrollHandlerState scroll_handler_state =
- impl().layer_tree_host_impl->scroll_affects_scroll_handler()
- ? ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER
- : ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
- impl().scheduler->SetTreePrioritiesAndScrollState(tree_priority,
- scroll_handler_state);
-
- // Notify the the client of this compositor via the output surface.
- // TODO(epenner): Route this to compositor-thread instead of output-surface
- // after GTFO refactor of compositor-thread (http://crbug/170828).
- if (impl().layer_tree_host_impl->output_surface()) {
- impl()
- .layer_tree_host_impl->output_surface()
- ->UpdateSmoothnessTakesPriority(tree_priority ==
- SMOOTHNESS_TAKES_PRIORITY);
- }
-}
-
-void ThreadProxy::PostDelayedAnimationTaskOnImplThread(
- const base::Closure& task,
- base::TimeDelta delay) {
- task_runner_provider_->ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE,
- task, delay);
-}
-
-void ThreadProxy::DidActivateSyncTree() {
- TRACE_EVENT0("cc", "ThreadProxy::DidActivateSyncTreeOnImplThread");
- DCHECK(task_runner_provider_->IsImplThread());
-
- if (impl().next_commit_waits_for_activation) {
- TRACE_EVENT_INSTANT0(
- "cc", "ReleaseCommitbyActivation", TRACE_EVENT_SCOPE_THREAD);
- DCHECK(impl().commit_completion_event);
- impl().commit_completion_event->Signal();
- impl().commit_completion_event = nullptr;
- impl().next_commit_waits_for_activation = false;
- }
-
- impl().last_processed_begin_main_frame_args =
- impl().last_begin_main_frame_args;
-}
-
-void ThreadProxy::WillPrepareTiles() {
- DCHECK(task_runner_provider_->IsImplThread());
- impl().scheduler->WillPrepareTiles();
-}
-
-void ThreadProxy::DidPrepareTiles() {
- DCHECK(task_runner_provider_->IsImplThread());
- impl().scheduler->DidPrepareTiles();
-}
-
-void ThreadProxy::DidCompletePageScaleAnimationOnImplThread() {
- DCHECK(task_runner_provider_->IsImplThread());
- impl().channel_impl->DidCompletePageScaleAnimation();
-}
-
-void ThreadProxy::OnDrawForOutputSurface() {
- DCHECK(task_runner_provider_->IsImplThread());
- impl().scheduler->OnDrawForOutputSurface();
-}
-
-void ThreadProxy::UpdateTopControlsState(TopControlsState constraints,
- TopControlsState current,
- bool animate) {
- main().channel_main->UpdateTopControlsStateOnImpl(constraints, current,
- animate);
-}
-
-void ThreadProxy::UpdateTopControlsStateOnImpl(TopControlsState constraints,
- TopControlsState current,
- bool animate) {
- DCHECK(task_runner_provider_->IsImplThread());
- impl().layer_tree_host_impl->top_controls_manager()->UpdateTopControlsState(
- constraints, current, animate);
-}
-
-void ThreadProxy::PostFrameTimingEventsOnImplThread(
- scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
- scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
- DCHECK(task_runner_provider_->IsImplThread());
- impl().channel_impl->PostFrameTimingEventsOnMain(
- std::move(composite_events), std::move(main_frame_events));
-}
-
-void ThreadProxy::PostFrameTimingEventsOnMain(
- scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
- scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
- DCHECK(task_runner_provider_->IsMainThread());
- main().layer_tree_host->RecordFrameTimingEvents(std::move(composite_events),
- std::move(main_frame_events));
-}
-
-base::WeakPtr<ProxyMain> ThreadProxy::GetMainWeakPtr() {
- return main_thread_weak_ptr_;
-}
-
-base::WeakPtr<ProxyImpl> ThreadProxy::GetImplWeakPtr() {
- return impl_thread_weak_ptr_;
-}
-
-} // namespace cc
diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h
deleted file mode 100644
index e10c57e..0000000
--- a/cc/trees/thread_proxy.h
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_TREES_THREAD_PROXY_H_
-#define CC_TREES_THREAD_PROXY_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "cc/animation/animation_events.h"
-#include "cc/base/completion_event.h"
-#include "cc/base/delayed_unique_notifier.h"
-#include "cc/scheduler/commit_earlyout_reason.h"
-#include "cc/scheduler/scheduler.h"
-#include "cc/trees/layer_tree_host_impl.h"
-#include "cc/trees/proxy.h"
-#include "cc/trees/threaded_channel.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace cc {
-
-class BeginFrameSource;
-class ChannelImpl;
-class ChannelMain;
-class ContextProvider;
-class InputHandlerClient;
-class LayerTreeHost;
-class ProxyImpl;
-class ProxyMain;
-class Scheduler;
-class ScopedThreadProxy;
-class ThreadedChannel;
-
-class CC_EXPORT ThreadProxy : public Proxy,
- public ProxyMain,
- public ProxyImpl,
- NON_EXPORTED_BASE(LayerTreeHostImplClient),
- NON_EXPORTED_BASE(SchedulerClient) {
- public:
- static scoped_ptr<Proxy> Create(
- LayerTreeHost* layer_tree_host,
- TaskRunnerProvider* task_runner_provider,
- scoped_ptr<BeginFrameSource> external_begin_frame_source);
-
- ~ThreadProxy() override;
-
- // Commits between the main and impl threads are processed through a pipeline
- // with the following stages. For efficiency we can early out at any stage if
- // we decide that no further processing is necessary.
- enum CommitPipelineStage {
- NO_PIPELINE_STAGE,
- ANIMATE_PIPELINE_STAGE,
- UPDATE_LAYERS_PIPELINE_STAGE,
- COMMIT_PIPELINE_STAGE,
- };
-
- struct MainThreadOnly {
- MainThreadOnly(ThreadProxy* proxy, LayerTreeHost* layer_tree_host);
- ~MainThreadOnly();
-
- const int layer_tree_host_id;
-
- LayerTreeHost* layer_tree_host;
-
- // The furthest pipeline stage which has been requested for the next
- // commit.
- CommitPipelineStage max_requested_pipeline_stage;
- // The commit pipeline stage that is currently being processed.
- CommitPipelineStage current_pipeline_stage;
- // The commit pipeline stage at which processing for the current commit
- // will stop. Only valid while we are executing the pipeline (i.e.,
- // |current_pipeline_stage| is set to a pipeline stage).
- CommitPipelineStage final_pipeline_stage;
-
- bool commit_waits_for_activation;
-
- bool started;
- bool prepare_tiles_pending;
- bool defer_commits;
-
- RendererCapabilities renderer_capabilities_main_thread_copy;
-
- // TODO(khushalsagar): Make this scoped_ptr<ChannelMain> when ProxyMain
- // and ProxyImpl are split.
- ChannelMain* channel_main;
-
- base::WeakPtrFactory<ThreadProxy> weak_factory;
- };
-
- // Accessed on the impl thread when the main thread is blocked for a commit.
- struct BlockedMainCommitOnly {
- BlockedMainCommitOnly();
- ~BlockedMainCommitOnly();
- LayerTreeHost* layer_tree_host;
- };
-
- struct CompositorThreadOnly {
- CompositorThreadOnly(
- ThreadProxy* proxy,
- int layer_tree_host_id,
- RenderingStatsInstrumentation* rendering_stats_instrumentation,
- scoped_ptr<BeginFrameSource> external_begin_frame_source);
- ~CompositorThreadOnly();
-
- const int layer_tree_host_id;
-
- scoped_ptr<Scheduler> scheduler;
-
- // Set when the main thread is waiting on a pending tree activation.
- bool next_commit_waits_for_activation;
-
- // Set when the main thread is waiting on a commit to complete or on a
- // pending tree activation.
- CompletionEvent* commit_completion_event;
-
- // Set when the next draw should post DidCommitAndDrawFrame to the main
- // thread.
- bool next_frame_is_newly_committed_frame;
-
- bool inside_draw;
-
- bool input_throttled_until_commit;
-
- // Whether a commit has been completed since the last time animations were
- // ticked. If this happens, we need to animate again.
- bool did_commit_after_animating;
-
- DelayedUniqueNotifier smoothness_priority_expiration_notifier;
-
- scoped_ptr<BeginFrameSource> external_begin_frame_source;
-
- RenderingStatsInstrumentation* rendering_stats_instrumentation;
-
- // Values used to keep track of frame durations. Used only in frame timing.
- BeginFrameArgs last_begin_main_frame_args;
- BeginFrameArgs last_processed_begin_main_frame_args;
-
- scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl;
-
- ChannelImpl* channel_impl;
-
- base::WeakPtrFactory<ThreadProxy> weak_factory;
- };
-
- const MainThreadOnly& main() const;
- const CompositorThreadOnly& impl() const;
- TaskRunnerProvider* task_runner_provider() { return task_runner_provider_; }
-
- // Proxy implementation
- void FinishAllRendering() override;
- bool IsStarted() const override;
- bool CommitToActiveTree() const override;
- void SetOutputSurface(OutputSurface* output_surface) override;
- void SetVisible(bool visible) override;
- void SetThrottleFrameProduction(bool throttle) override;
- const RendererCapabilities& GetRendererCapabilities() const override;
- void SetNeedsAnimate() override;
- void SetNeedsUpdateLayers() override;
- void SetNeedsCommit() override;
- void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
- void SetNextCommitWaitsForActivation() override;
- void NotifyInputThrottledUntilCommit() override;
- void SetDeferCommits(bool defer_commits) override;
- bool CommitRequested() const override;
- bool BeginMainFrameRequested() const override;
- void MainThreadHasStoppedFlinging() override;
- void Start() override;
- void Stop() override;
- bool SupportsImplScrolling() const override;
- bool MainFrameWillHappenForTesting() override;
- void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override;
- void SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) override;
- void ReleaseOutputSurface() override;
- void UpdateTopControlsState(TopControlsState constraints,
- TopControlsState current,
- bool animate) override;
-
- // LayerTreeHostImplClient implementation
- void UpdateRendererCapabilitiesOnImplThread() override;
- void DidLoseOutputSurfaceOnImplThread() override;
- void CommitVSyncParameters(base::TimeTicks timebase,
- base::TimeDelta interval) override;
- void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override;
- void DidSwapBuffersOnImplThread() override;
- void DidSwapBuffersCompleteOnImplThread() override;
- void OnResourcelessSoftareDrawStateChanged(bool resourceless_draw) override;
- void OnCanDrawStateChanged(bool can_draw) override;
- void NotifyReadyToActivate() override;
- void NotifyReadyToDraw() override;
- // Please call these 3 functions through
- // LayerTreeHostImpl's SetNeedsRedraw(), SetNeedsRedrawRect() and
- // SetNeedsOneBeginImplFrame().
- void SetNeedsRedrawOnImplThread() override;
- void SetNeedsRedrawRectOnImplThread(const gfx::Rect& dirty_rect) override;
- void SetNeedsOneBeginImplFrameOnImplThread() override;
- void SetNeedsPrepareTilesOnImplThread() override;
- void SetNeedsCommitOnImplThread() override;
- void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
- void PostAnimationEventsToMainThreadOnImplThread(
- scoped_ptr<AnimationEventsVector> queue) override;
- bool IsInsideDraw() override;
- void RenewTreePriority() override;
- void PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
- base::TimeDelta delay) override;
- void DidActivateSyncTree() override;
- void WillPrepareTiles() override;
- void DidPrepareTiles() override;
- void DidCompletePageScaleAnimationOnImplThread() override;
- void OnDrawForOutputSurface() override;
- // This should only be called by LayerTreeHostImpl::PostFrameTimingEvents.
- void PostFrameTimingEventsOnImplThread(
- scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
- scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
- override;
-
- // SchedulerClient implementation
- void WillBeginImplFrame(const BeginFrameArgs& args) override;
- void DidFinishImplFrame() override;
- void ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) override;
- DrawResult ScheduledActionDrawAndSwapIfPossible() override;
- DrawResult ScheduledActionDrawAndSwapForced() override;
- void ScheduledActionCommit() override;
- void ScheduledActionActivateSyncTree() override;
- void ScheduledActionBeginOutputSurfaceCreation() override;
- void ScheduledActionPrepareTiles() override;
- void ScheduledActionInvalidateOutputSurface() override;
- void SendBeginFramesToChildren(const BeginFrameArgs& args) override;
- void SendBeginMainFrameNotExpectedSoon() override;
-
- // ProxyMain implementation
- void SetChannel(scoped_ptr<ThreadedChannel> threaded_channel) override;
-
- protected:
- ThreadProxy(LayerTreeHost* layer_tree_host,
- TaskRunnerProvider* task_runner_provider,
- scoped_ptr<BeginFrameSource> external_begin_frame_source);
-
- private:
- friend class ThreadProxyForTest;
-
- // ProxyMain implementation.
- base::WeakPtr<ProxyMain> GetMainWeakPtr() override;
- void DidCompleteSwapBuffers() override;
- void SetRendererCapabilitiesMainCopy(
- const RendererCapabilities& capabilities) override;
- void BeginMainFrameNotExpectedSoon() override;
- void DidCommitAndDrawFrame() override;
- void SetAnimationEvents(scoped_ptr<AnimationEventsVector> queue) override;
- void DidLoseOutputSurface() override;
- void RequestNewOutputSurface() override;
- void DidInitializeOutputSurface(
- bool success,
- const RendererCapabilities& capabilities) override;
- void DidCompletePageScaleAnimation() override;
- void PostFrameTimingEventsOnMain(
- scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
- scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
- override;
- void BeginMainFrame(
- scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) override;
-
- // ProxyImpl implementation
- base::WeakPtr<ProxyImpl> GetImplWeakPtr() override;
- void SetThrottleFrameProductionOnImpl(bool throttle) override;
- void UpdateTopControlsStateOnImpl(TopControlsState constraints,
- TopControlsState current,
- bool animate) override;
- void InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) override;
- void MainThreadHasStoppedFlingingOnImpl() override;
- void SetInputThrottledUntilCommitOnImpl(bool is_throttled) override;
- void SetDeferCommitsOnImpl(bool defer_commits) const override;
- void FinishAllRenderingOnImpl(CompletionEvent* completion) override;
- void SetVisibleOnImpl(bool visible) override;
- void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) override;
- void FinishGLOnImpl(CompletionEvent* completion) override;
- void MainFrameWillHappenOnImplForTesting(
- CompletionEvent* completion,
- bool* main_frame_will_happen) override;
- void SetNeedsCommitOnImpl() override;
- void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) override;
- void BeginMainFrameAbortedOnImpl(
- CommitEarlyOutReason reason,
- base::TimeTicks main_thread_start_time) override;
- void StartCommitOnImpl(CompletionEvent* completion,
- LayerTreeHost* layer_tree_host,
- base::TimeTicks main_thread_start_time,
- bool hold_commit_for_activation) override;
- void InitializeImplOnImpl(CompletionEvent* completion,
- LayerTreeHost* layer_tree_host) override;
- void LayerTreeHostClosedOnImpl(CompletionEvent* completion) override;
-
- // Returns |true| if the request was actually sent, |false| if one was
- // already outstanding.
- bool SendCommitRequestToImplThreadIfNeeded(
- CommitPipelineStage required_stage);
-
- // Called on impl thread.
- struct SchedulerStateRequest;
-
- DrawResult DrawSwapInternal(bool forced_draw);
-
- TaskRunnerProvider* task_runner_provider_;
-
- // Use accessors instead of this variable directly.
- MainThreadOnly main_thread_only_vars_unsafe_;
- MainThreadOnly& main();
-
- // Use accessors instead of this variable directly.
- BlockedMainCommitOnly main_thread_blocked_commit_vars_unsafe_;
- BlockedMainCommitOnly& blocked_main_commit();
-
- // Use accessors instead of this variable directly.
- CompositorThreadOnly compositor_thread_vars_unsafe_;
- CompositorThreadOnly& impl();
-
- // TODO(khushalsagar): Remove this. Temporary variable to hold the channel.
- scoped_ptr<ThreadedChannel> threaded_channel_;
-
- base::WeakPtr<ThreadProxy> main_thread_weak_ptr_;
- base::WeakPtr<ThreadProxy> impl_thread_weak_ptr_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadProxy);
-};
-
-} // namespace cc
-
-#endif // CC_TREES_THREAD_PROXY_H_
diff --git a/cc/trees/threaded_channel.cc b/cc/trees/threaded_channel.cc
index 37ed58f..3d2eb33 100644
--- a/cc/trees/threaded_channel.cc
+++ b/cc/trees/threaded_channel.cc
@@ -7,222 +7,312 @@
#include "base/bind.h"
#include "base/single_thread_task_runner.h"
#include "base/trace_event/trace_event.h"
+#include "cc/trees/layer_tree_host.h"
namespace cc {
-scoped_ptr<ThreadedChannel> ThreadedChannel::Create(
- ThreadProxy* thread_proxy,
- TaskRunnerProvider* task_runner_provider) {
- return make_scoped_ptr(
- new ThreadedChannel(thread_proxy, task_runner_provider));
+ThreadedChannel::ThreadedChannel(ProxyMain* proxy_main,
+ TaskRunnerProvider* task_runner_provider)
+ : task_runner_provider_(task_runner_provider),
+ main_thread_only_vars_unsafe_(proxy_main),
+ compositor_thread_vars_unsafe_(
+ main()
+ .proxy_main_weak_factory.GetWeakPtr()) {
+ DCHECK(IsMainThread());
}
-ThreadedChannel::ThreadedChannel(ThreadProxy* thread_proxy,
- TaskRunnerProvider* task_runner_provider)
- : proxy_main_(thread_proxy),
- proxy_impl_(thread_proxy),
- task_runner_provider_(task_runner_provider) {}
+ThreadedChannel::~ThreadedChannel() {
+ TRACE_EVENT0("cc", "ThreadChannel::~ThreadChannel");
+ DCHECK(IsMainThread());
+ DCHECK(!IsInitialized());
+}
void ThreadedChannel::SetThrottleFrameProductionOnImpl(bool throttle) {
+ DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
FROM_HERE, base::Bind(&ProxyImpl::SetThrottleFrameProductionOnImpl,
- proxy_impl_->GetImplWeakPtr(), throttle));
+ proxy_impl_weak_ptr_, throttle));
}
void ThreadedChannel::UpdateTopControlsStateOnImpl(TopControlsState constraints,
TopControlsState current,
bool animate) {
+ DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
FROM_HERE,
- base::Bind(&ProxyImpl::UpdateTopControlsStateOnImpl,
- proxy_impl_->GetImplWeakPtr(), constraints, current, animate));
+ base::Bind(&ProxyImpl::UpdateTopControlsStateOnImpl, proxy_impl_weak_ptr_,
+ constraints, current, animate));
}
void ThreadedChannel::InitializeOutputSurfaceOnImpl(
OutputSurface* output_surface) {
+ DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
FROM_HERE, base::Bind(&ProxyImpl::InitializeOutputSurfaceOnImpl,
- proxy_impl_->GetImplWeakPtr(), output_surface));
+ proxy_impl_weak_ptr_, output_surface));
}
void ThreadedChannel::MainThreadHasStoppedFlingingOnImpl() {
+ DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
FROM_HERE, base::Bind(&ProxyImpl::MainThreadHasStoppedFlingingOnImpl,
- proxy_impl_->GetImplWeakPtr()));
+ proxy_impl_weak_ptr_));
}
void ThreadedChannel::SetInputThrottledUntilCommitOnImpl(bool is_throttled) {
+ DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
FROM_HERE, base::Bind(&ProxyImpl::SetInputThrottledUntilCommitOnImpl,
- proxy_impl_->GetImplWeakPtr(), is_throttled));
+ proxy_impl_weak_ptr_, is_throttled));
}
void ThreadedChannel::SetDeferCommitsOnImpl(bool defer_commits) {
+ DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
FROM_HERE, base::Bind(&ProxyImpl::SetDeferCommitsOnImpl,
- proxy_impl_->GetImplWeakPtr(), defer_commits));
-}
-
-void ThreadedChannel::FinishAllRenderingOnImpl(CompletionEvent* completion) {
- ImplThreadTaskRunner()->PostTask(
- FROM_HERE, base::Bind(&ProxyImpl::FinishAllRenderingOnImpl,
- proxy_impl_->GetImplWeakPtr(), completion));
+ proxy_impl_weak_ptr_, defer_commits));
}
void ThreadedChannel::SetNeedsCommitOnImpl() {
- ImplThreadTaskRunner()->PostTask(FROM_HERE,
- base::Bind(&ProxyImpl::SetNeedsCommitOnImpl,
- proxy_impl_->GetImplWeakPtr()));
+ DCHECK(IsMainThread());
+ ImplThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&ProxyImpl::SetNeedsCommitOnImpl, proxy_impl_weak_ptr_));
}
void ThreadedChannel::BeginMainFrameAbortedOnImpl(
CommitEarlyOutReason reason,
base::TimeTicks main_thread_start_time) {
+ DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
- FROM_HERE, base::Bind(&ProxyImpl::BeginMainFrameAbortedOnImpl,
- proxy_impl_->GetImplWeakPtr(), reason,
- main_thread_start_time));
+ FROM_HERE,
+ base::Bind(&ProxyImpl::BeginMainFrameAbortedOnImpl, proxy_impl_weak_ptr_,
+ reason, main_thread_start_time));
}
void ThreadedChannel::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
+ DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
FROM_HERE, base::Bind(&ProxyImpl::SetNeedsRedrawOnImpl,
- proxy_impl_->GetImplWeakPtr(), damage_rect));
-}
-
-void ThreadedChannel::StartCommitOnImpl(CompletionEvent* completion,
- LayerTreeHost* layer_tree_host,
- base::TimeTicks main_thread_start_time,
- bool hold_commit_for_activation) {
- ImplThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&ProxyImpl::StartCommitOnImpl, proxy_impl_->GetImplWeakPtr(),
- completion, layer_tree_host, main_thread_start_time,
- hold_commit_for_activation));
+ proxy_impl_weak_ptr_, damage_rect));
}
-void ThreadedChannel::InitializeImplOnImpl(CompletionEvent* completion,
- LayerTreeHost* layer_tree_host) {
+void ThreadedChannel::SetVisibleOnImpl(bool visible) {
+ DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
FROM_HERE,
- base::Bind(&ProxyImpl::InitializeImplOnImpl,
- base::Unretained(proxy_impl_), completion, layer_tree_host));
-}
-
-void ThreadedChannel::LayerTreeHostClosedOnImpl(CompletionEvent* completion) {
- ImplThreadTaskRunner()->PostTask(
- FROM_HERE, base::Bind(&ProxyImpl::LayerTreeHostClosedOnImpl,
- proxy_impl_->GetImplWeakPtr(), completion));
- proxy_impl_ = nullptr;
+ base::Bind(&ProxyImpl::SetVisibleOnImpl, proxy_impl_weak_ptr_, visible));
}
-void ThreadedChannel::SetVisibleOnImpl(bool visible) {
+void ThreadedChannel::FinishAllRenderingOnImpl(CompletionEvent* completion) {
+ DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
- FROM_HERE, base::Bind(&ProxyImpl::SetVisibleOnImpl,
- proxy_impl_->GetImplWeakPtr(), visible));
+ FROM_HERE, base::Bind(&ProxyImpl::FinishAllRenderingOnImpl,
+ proxy_impl_weak_ptr_, completion));
}
void ThreadedChannel::ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) {
+ DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
FROM_HERE, base::Bind(&ProxyImpl::ReleaseOutputSurfaceOnImpl,
- proxy_impl_->GetImplWeakPtr(), completion));
-}
-
-void ThreadedChannel::FinishGLOnImpl(CompletionEvent* completion) {
- ImplThreadTaskRunner()->PostTask(
- FROM_HERE, base::Bind(&ProxyImpl::FinishGLOnImpl,
- proxy_impl_->GetImplWeakPtr(), completion));
+ proxy_impl_weak_ptr_, completion));
}
void ThreadedChannel::MainFrameWillHappenOnImplForTesting(
CompletionEvent* completion,
bool* main_frame_will_happen) {
+ DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
- FROM_HERE, base::Bind(&ProxyImpl::MainFrameWillHappenOnImplForTesting,
- proxy_impl_->GetImplWeakPtr(), completion,
- main_frame_will_happen));
+ FROM_HERE,
+ base::Bind(&ProxyImpl::MainFrameWillHappenOnImplForTesting,
+ proxy_impl_weak_ptr_, completion, main_frame_will_happen));
+}
+
+void ThreadedChannel::StartCommitOnImpl(CompletionEvent* completion,
+ LayerTreeHost* layer_tree_host,
+ base::TimeTicks main_thread_start_time,
+ bool hold_commit_for_activation) {
+ DCHECK(IsMainThread());
+ ImplThreadTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&ProxyImpl::StartCommitOnImpl, proxy_impl_weak_ptr_,
+ completion, layer_tree_host, main_thread_start_time,
+ hold_commit_for_activation));
+}
+
+void ThreadedChannel::SynchronouslyInitializeImpl(
+ LayerTreeHost* layer_tree_host,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+ TRACE_EVENT0("cc", "ThreadChannel::SynchronouslyInitializeImpl");
+ DCHECK(IsMainThread());
+ {
+ DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+ CompletionEvent completion;
+ ImplThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&ThreadedChannel::InitializeImplOnImpl,
+ base::Unretained(this), &completion, layer_tree_host,
+ base::Passed(&external_begin_frame_source)));
+ completion.Wait();
+ }
+ main().initialized = true;
+}
+
+void ThreadedChannel::SynchronouslyCloseImpl() {
+ TRACE_EVENT0("cc", "ThreadChannel::~SynchronouslyCloseImpl");
+ DCHECK(IsMainThread());
+
+ // Synchronously finishes pending GL operations and deletes the impl.
+ // The two steps are done as separate post tasks, so that tasks posted
+ // by the GL implementation due to the Finish can be executed by the
+ // renderer before shutting it down.
+ {
+ DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+ CompletionEvent completion;
+ ImplThreadTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&ProxyImpl::FinishGLOnImpl, proxy_impl_weak_ptr_,
+ &completion));
+ completion.Wait();
+ }
+ {
+ DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+ CompletionEvent completion;
+ ImplThreadTaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&ThreadedChannel::CloseImplOnImpl,
+ base::Unretained(this), &completion));
+ completion.Wait();
+ }
+ main().proxy_main_weak_factory.InvalidateWeakPtrs();
+ main().initialized = false;
}
void ThreadedChannel::DidCompleteSwapBuffers() {
+ DCHECK(IsImplThread());
MainThreadTaskRunner()->PostTask(
FROM_HERE, base::Bind(&ProxyMain::DidCompleteSwapBuffers,
- proxy_main_->GetMainWeakPtr()));
+ impl().proxy_main_weak_ptr));
}
void ThreadedChannel::SetRendererCapabilitiesMainCopy(
const RendererCapabilities& capabilities) {
+ DCHECK(IsImplThread());
MainThreadTaskRunner()->PostTask(
- FROM_HERE, base::Bind(&ProxyMain::SetRendererCapabilitiesMainCopy,
- proxy_main_->GetMainWeakPtr(), capabilities));
+ FROM_HERE, base::Bind(&ProxyMain::SetRendererCapabilities,
+ impl().proxy_main_weak_ptr, capabilities));
}
void ThreadedChannel::BeginMainFrameNotExpectedSoon() {
+ DCHECK(IsImplThread());
MainThreadTaskRunner()->PostTask(
FROM_HERE, base::Bind(&ProxyMain::BeginMainFrameNotExpectedSoon,
- proxy_main_->GetMainWeakPtr()));
+ impl().proxy_main_weak_ptr));
}
void ThreadedChannel::DidCommitAndDrawFrame() {
+ DCHECK(IsImplThread());
MainThreadTaskRunner()->PostTask(FROM_HERE,
base::Bind(&ProxyMain::DidCommitAndDrawFrame,
- proxy_main_->GetMainWeakPtr()));
+ impl().proxy_main_weak_ptr));
}
void ThreadedChannel::SetAnimationEvents(
scoped_ptr<AnimationEventsVector> queue) {
+ DCHECK(IsImplThread());
MainThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&ProxyMain::SetAnimationEvents, proxy_main_->GetMainWeakPtr(),
- base::Passed(&queue)));
+ FROM_HERE, base::Bind(&ProxyMain::SetAnimationEvents,
+ impl().proxy_main_weak_ptr, base::Passed(&queue)));
}
void ThreadedChannel::DidLoseOutputSurface() {
- MainThreadTaskRunner()->PostTask(FROM_HERE,
- base::Bind(&ProxyMain::DidLoseOutputSurface,
- proxy_main_->GetMainWeakPtr()));
+ DCHECK(IsImplThread());
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&ProxyMain::DidLoseOutputSurface, impl().proxy_main_weak_ptr));
}
void ThreadedChannel::RequestNewOutputSurface() {
+ DCHECK(IsImplThread());
MainThreadTaskRunner()->PostTask(
FROM_HERE, base::Bind(&ProxyMain::RequestNewOutputSurface,
- proxy_main_->GetMainWeakPtr()));
+ impl().proxy_main_weak_ptr));
}
void ThreadedChannel::DidInitializeOutputSurface(
bool success,
const RendererCapabilities& capabilities) {
+ DCHECK(IsImplThread());
MainThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&ProxyMain::DidInitializeOutputSurface,
- proxy_main_->GetMainWeakPtr(), success, capabilities));
+ FROM_HERE, base::Bind(&ProxyMain::DidInitializeOutputSurface,
+ impl().proxy_main_weak_ptr, success, capabilities));
}
void ThreadedChannel::DidCompletePageScaleAnimation() {
+ DCHECK(IsImplThread());
MainThreadTaskRunner()->PostTask(
FROM_HERE, base::Bind(&ProxyMain::DidCompletePageScaleAnimation,
- proxy_main_->GetMainWeakPtr()));
+ impl().proxy_main_weak_ptr));
}
void ThreadedChannel::PostFrameTimingEventsOnMain(
scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
+ DCHECK(IsImplThread());
MainThreadTaskRunner()->PostTask(
FROM_HERE, base::Bind(&ProxyMain::PostFrameTimingEventsOnMain,
- proxy_main_->GetMainWeakPtr(),
+ impl().proxy_main_weak_ptr,
base::Passed(std::move(composite_events)),
base::Passed(std::move(main_frame_events))));
}
void ThreadedChannel::BeginMainFrame(
scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
+ DCHECK(IsImplThread());
MainThreadTaskRunner()->PostTask(
FROM_HERE,
- base::Bind(&ProxyMain::BeginMainFrame, proxy_main_->GetMainWeakPtr(),
+ base::Bind(&ProxyMain::BeginMainFrame, impl().proxy_main_weak_ptr,
base::Passed(&begin_main_frame_state)));
}
-ThreadedChannel::~ThreadedChannel() {
- TRACE_EVENT0("cc", "ThreadChannel::~ThreadChannel");
+ProxyImpl* ThreadedChannel::GetProxyImplForTesting() const {
+ return impl().proxy_impl.get();
+}
+
+scoped_ptr<ProxyImpl> ThreadedChannel::CreateProxyImpl(
+ ChannelImpl* channel_impl,
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+ DCHECK(IsImplThread());
+ return ProxyImpl::Create(channel_impl, layer_tree_host, task_runner_provider,
+ std::move(external_begin_frame_source));
+}
+
+void ThreadedChannel::InitializeImplOnImpl(
+ CompletionEvent* completion,
+ LayerTreeHost* layer_tree_host,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+ DCHECK(IsImplThread());
+ impl().proxy_impl =
+ CreateProxyImpl(this, layer_tree_host, task_runner_provider_,
+ std::move(external_begin_frame_source));
+ impl().proxy_impl_weak_factory = make_scoped_ptr(
+ new base::WeakPtrFactory<ProxyImpl>(impl().proxy_impl.get()));
+ proxy_impl_weak_ptr_ = impl().proxy_impl_weak_factory->GetWeakPtr();
+ completion->Signal();
+}
+
+void ThreadedChannel::CloseImplOnImpl(CompletionEvent* completion) {
+ DCHECK(IsImplThread());
+
+ // We must destroy the factory and ensure that the ProxyImpl weak pointers are
+ // invalidated before destroying proxy_impl.
+ impl().proxy_impl_weak_factory.reset();
+
+ impl().proxy_impl.reset();
+ completion->Signal();
+}
+
+bool ThreadedChannel::IsInitialized() const {
+ return main().initialized;
}
base::SingleThreadTaskRunner* ThreadedChannel::MainThreadTaskRunner() const {
@@ -233,4 +323,49 @@ base::SingleThreadTaskRunner* ThreadedChannel::ImplThreadTaskRunner() const {
return task_runner_provider_->ImplThreadTaskRunner();
}
+bool ThreadedChannel::IsMainThread() const {
+ return task_runner_provider_->IsMainThread();
+}
+
+bool ThreadedChannel::IsImplThread() const {
+ return task_runner_provider_->IsImplThread();
+}
+
+ThreadedChannel::MainThreadOnly& ThreadedChannel::main() {
+ DCHECK(task_runner_provider_->IsMainThread());
+ return main_thread_only_vars_unsafe_;
+}
+
+const ThreadedChannel::MainThreadOnly& ThreadedChannel::main() const {
+ DCHECK(task_runner_provider_->IsMainThread());
+ return main_thread_only_vars_unsafe_;
+}
+
+ThreadedChannel::CompositorThreadOnly& ThreadedChannel::impl() {
+ DCHECK(task_runner_provider_->IsImplThread());
+ return compositor_thread_vars_unsafe_;
+}
+
+const ThreadedChannel::CompositorThreadOnly& ThreadedChannel::impl() const {
+ DCHECK(task_runner_provider_->IsImplThread());
+ return compositor_thread_vars_unsafe_;
+}
+
+ThreadedChannel::MainThreadOnly::MainThreadOnly(ProxyMain* proxy_main)
+ : proxy_main_weak_factory(proxy_main), initialized(false) {}
+
+ThreadedChannel::MainThreadOnly::~MainThreadOnly() {}
+
+ThreadedChannel::CompositorThreadOnly::CompositorThreadOnly(
+ base::WeakPtr<ProxyMain> proxy_main_weak_ptr)
+ : proxy_main_weak_ptr(proxy_main_weak_ptr) {}
+
+ThreadedChannel::CompositorThreadOnly::~CompositorThreadOnly() {}
+
+scoped_ptr<ThreadedChannel> ThreadedChannel::Create(
+ ProxyMain* proxy_main,
+ TaskRunnerProvider* task_runner_provider) {
+ return make_scoped_ptr(new ThreadedChannel(proxy_main, task_runner_provider));
+}
+
} // namespace cc
diff --git a/cc/trees/threaded_channel.h b/cc/trees/threaded_channel.h
index ca7fc04..5d10f4a 100644
--- a/cc/trees/threaded_channel.h
+++ b/cc/trees/threaded_channel.h
@@ -7,13 +7,13 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "cc/base/cc_export.h"
#include "cc/trees/channel_impl.h"
#include "cc/trees/channel_main.h"
#include "cc/trees/proxy_common.h"
#include "cc/trees/proxy_impl.h"
#include "cc/trees/proxy_main.h"
-#include "cc/trees/thread_proxy.h"
namespace base {
class SingleThreadTaskRunner;
@@ -22,9 +22,9 @@ class SingleThreadTaskRunner;
namespace cc {
class ChannelImpl;
class ChannelMain;
+class LayerTreeHost;
class ProxyImpl;
class ProxyMain;
-class ThreadProxy;
// An implementation of ChannelMain and ChannelImpl that sends commands between
// ProxyMain and ProxyImpl across thread boundaries.
@@ -39,8 +39,8 @@ class ThreadProxy;
// ProxyMain->Start() |
// | ThreadedChannel
// ---------------------------------------------------------------------------
-// ChannelMain::InitializeImpl ---PostTask---> ThreadedChannel::
-// InitializeImplOnImplThread
+// ChannelMain::SynchronouslyInitializeImpl ---PostTask---> ThreadedChannel::
+// InitializeImplOnImpl
// |
// ProxyImpl::Create
// |
@@ -56,20 +56,27 @@ class ThreadProxy;
// ProxyMain->RequestNewOutputSurface()<----PostTask--------
// .
// .
-// ProxyMain->LayerTreeHostClosed
+// ProxyMain->Stop()
// |
// ---------------------------------------------------------------------------
-// ChannelMain::SetLayerTreeClosedOnImpl---PostTask---> ProxyImpl->
-// SetLayerTreeClosed
+// ChannelMain::SynchronouslyCloseImpl ---PostTask---> ThreadedChannel::
+// CloseImplOnImpl
// ----------------------------------------------------------------------------
+//
+// ThreadedChannel is created and destroyed on the main thread but can be
+// called from main or impl thread. It is safe for the Threadedchannel to be
+// called on the impl thread because:
+// 1) The only impl-threaded callers of ThreadedChannel are the ThreadedChannel
+// itself and ProxyImpl which is created and owned by the ThreadedChannel.
+// 2) ThreadedChannel blocks the main thread in
+// ThreadedChannel::SynchronouslyCloseImpl to wait for the impl-thread teardown
+// to complete, so there is no risk of any queued tasks calling it on the impl
+// thread after it has been deleted on the main thread.
class CC_EXPORT ThreadedChannel : public ChannelMain, public ChannelImpl {
public:
static scoped_ptr<ThreadedChannel> Create(
- // TODO(khushalsagar): Make this ProxyMain* and write the initialization
- // sequence. Currently ThreadProxy implements both so we pass the pointer
- // and set ProxyImpl.
- ThreadProxy* thread_proxy,
+ ProxyMain* proxy_main,
TaskRunnerProvider* task_runner_provider);
~ThreadedChannel() override;
@@ -93,7 +100,6 @@ class CC_EXPORT ThreadedChannel : public ChannelMain, public ChannelImpl {
// Blocking calls to ProxyImpl
void FinishAllRenderingOnImpl(CompletionEvent* completion) override;
void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) override;
- void FinishGLOnImpl(CompletionEvent* completion) override;
void MainFrameWillHappenOnImplForTesting(
CompletionEvent* completion,
bool* main_frame_will_happen) override;
@@ -101,9 +107,10 @@ class CC_EXPORT ThreadedChannel : public ChannelMain, public ChannelImpl {
LayerTreeHost* layer_tree_host,
base::TimeTicks main_thread_start_time,
bool hold_commit_for_activation) override;
- void InitializeImplOnImpl(CompletionEvent* completion,
- LayerTreeHost* layer_tree_host) override;
- void LayerTreeHostClosedOnImpl(CompletionEvent* completion) override;
+ void SynchronouslyInitializeImpl(
+ LayerTreeHost* layer_tree_host,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source) override;
+ void SynchronouslyCloseImpl() override;
// ChannelImpl Implementation
void DidCompleteSwapBuffers() override;
@@ -125,23 +132,84 @@ class CC_EXPORT ThreadedChannel : public ChannelMain, public ChannelImpl {
void BeginMainFrame(
scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) override;
+ // Should be called on impl thread only.
+ ProxyImpl* GetProxyImplForTesting() const;
+
protected:
- ThreadedChannel(ThreadProxy* thread_proxy,
+ ThreadedChannel(ProxyMain* proxy_main,
TaskRunnerProvider* task_runner_provider);
+ // Virtual for testing.
+ virtual scoped_ptr<ProxyImpl> CreateProxyImpl(
+ ChannelImpl* channel_impl,
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source);
+
private:
+ // The members of this struct should be accessed on the main thread only.
+ struct MainThreadOnly {
+ explicit MainThreadOnly(ProxyMain* proxy_main);
+ ~MainThreadOnly();
+
+ base::WeakPtrFactory<ProxyMain> proxy_main_weak_factory;
+ bool initialized;
+ };
+
+ // The members of this struct should be accessed on the impl thread only.
+ struct CompositorThreadOnly {
+ explicit CompositorThreadOnly(base::WeakPtr<ProxyMain> proxy_main_weak_ptr);
+ ~CompositorThreadOnly();
+
+ scoped_ptr<ProxyImpl> proxy_impl;
+
+ // We use a scoped_ptr for the weak ptr factory here since the factory is
+ // created after ProxyImpl is created in InitializeImplOnImpl. Since the
+ // weak ptrs are needed only by the ThreadedChannel to safely post tasks on
+ // ProxyImpl to be run on the impl thread, we avoid creating it in ProxyImpl
+ // and ensure that it is destroyed before ProxyImpl during the impl-thread
+ // tear down in CloseImplOnImpl.
+ scoped_ptr<base::WeakPtrFactory<ProxyImpl>> proxy_impl_weak_factory;
+
+ // Used on the impl thread to queue calls to ProxyMain to be run on the main
+ // thread. Since the weak pointer is invalidated after the impl-thread tear
+ // down in SynchronouslyCloseImpl, this ensures that any tasks posted to
+ // ProxyMain from the impl thread are abandoned after the impl side has been
+ // destroyed.
+ base::WeakPtr<ProxyMain> proxy_main_weak_ptr;
+ };
+
+ // Called on impl thread.
+ void InitializeImplOnImpl(
+ CompletionEvent* completion,
+ LayerTreeHost* layer_tree_host,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source);
+ void CloseImplOnImpl(CompletionEvent* completion);
+
+ bool IsInitialized() const;
+
base::SingleThreadTaskRunner* MainThreadTaskRunner() const;
base::SingleThreadTaskRunner* ImplThreadTaskRunner() const;
+ bool IsMainThread() const;
+ bool IsImplThread() const;
+
+ TaskRunnerProvider* task_runner_provider_;
- ProxyMain* proxy_main_;
+ MainThreadOnly& main();
+ const MainThreadOnly& main() const;
- ProxyImpl* proxy_impl_;
+ CompositorThreadOnly& impl();
+ const CompositorThreadOnly& impl() const;
- TaskRunnerProvider* task_runner_provider_;
+ // Use accessors instead of this variable directly.
+ MainThreadOnly main_thread_only_vars_unsafe_;
- scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ // Use accessors instead of this variable directly.
+ CompositorThreadOnly compositor_thread_vars_unsafe_;
- scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner_;
+ // Used on the main thread to safely queue calls to ProxyImpl to be run on the
+ // impl thread.
+ base::WeakPtr<ProxyImpl> proxy_impl_weak_ptr_;
DISALLOW_COPY_AND_ASSIGN(ThreadedChannel);
};
diff --git a/cc/trees/threaded_channel_unittest.cc b/cc/trees/threaded_channel_unittest.cc
index 152ff59..17350d8 100644
--- a/cc/trees/threaded_channel_unittest.cc
+++ b/cc/trees/threaded_channel_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -13,13 +13,12 @@ namespace cc {
// The ThreadedChannel tests are run only for threaded and direct mode.
class ThreadedChannelTest : public LayerTreeTest {
protected:
- ThreadedChannelTest() : thread_proxy_(nullptr), calls_received_(0) {}
+ ThreadedChannelTest() : calls_received_(0) {}
~ThreadedChannelTest() override {}
void BeginTest() override {
DCHECK(HasImplThread());
- thread_proxy_ = static_cast<ThreadProxy*>(proxy());
BeginChannelTest();
};
virtual void BeginChannelTest() {}
@@ -36,9 +35,6 @@ class ThreadedChannelTest : public LayerTreeTest {
void AfterTest() override {}
- // TODO(khushalsagar): Remove this once ProxyImpl is added to the
- // LayerTreeTest.
- ThreadProxy* thread_proxy_;
int calls_received_;
private:
@@ -47,8 +43,6 @@ class ThreadedChannelTest : public LayerTreeTest {
class ThreadedChannelTestInitializationAndShutdown
: public ThreadedChannelTest {
- void InitializeImplOnImpl() override { calls_received_++; }
-
void SetVisibleOnImpl(bool visible) override { calls_received_++; }
void ReceivedRequestNewOutputSurface() override { calls_received_++; }
@@ -69,10 +63,9 @@ class ThreadedChannelTestInitializationAndShutdown
EndTest();
}
- void WillCloseLayerTreeHostOnImpl() override { calls_received_++; }
void FinishGLOnImpl() override { calls_received_++; }
- void AfterTest() override { EXPECT_EQ(8, calls_received_); }
+ void AfterTest() override { EXPECT_EQ(6, calls_received_); }
};
MULTI_THREAD_DIRECT_RENDERER_TEST_F(
@@ -246,7 +239,7 @@ class ThreadedChannelTestBeginMainFrameNotExpectedSoon
void BeginChannelTest() override { PostOnImplThread(); }
void StartTestOnImplThread() override {
- thread_proxy_->SendBeginMainFrameNotExpectedSoon();
+ GetProxyImplForTest()->SendBeginMainFrameNotExpectedSoon();
}
void ReceivedBeginMainFrameNotExpectedSoon() override {
@@ -266,7 +259,7 @@ class ThreadedChannelTestSetAnimationEvents : public ThreadedChannelTest {
void StartTestOnImplThread() override {
scoped_ptr<AnimationEventsVector> events(
make_scoped_ptr(new AnimationEventsVector));
- thread_proxy_->PostAnimationEventsToMainThreadOnImplThread(
+ GetProxyImplForTest()->PostAnimationEventsToMainThreadOnImplThread(
std::move(events));
}
@@ -284,7 +277,7 @@ class ThreadedChannelTestLoseOutputSurface : public ThreadedChannelTest {
void BeginChannelTest() override { PostOnImplThread(); }
void StartTestOnImplThread() override {
- thread_proxy_->DidLoseOutputSurfaceOnImplThread();
+ GetProxyImplForTest()->DidLoseOutputSurfaceOnImplThread();
}
void ReceivedDidLoseOutputSurface() override {
@@ -301,7 +294,7 @@ class ThreadedChannelTestPageScaleAnimation : public ThreadedChannelTest {
void BeginChannelTest() override { PostOnImplThread(); }
void StartTestOnImplThread() override {
- thread_proxy_->DidCompletePageScaleAnimationOnImplThread();
+ GetProxyImplForTest()->DidCompletePageScaleAnimationOnImplThread();
}
void ReceivedDidCompletePageScaleAnimation() override {