diff options
author | simonhong <simonhong@chromium.org> | 2014-11-11 12:50:22 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-11 20:50:50 +0000 |
commit | a7e3ac41cb5b104e6d96fc31c2a1e5330b601ec7 (patch) | |
tree | 26ce9470e916e4ea28dcf3a7ea5d10e771f31a8b | |
parent | b61084c674e7973e5cbcfb4d03159f4abd8444b9 (diff) | |
download | chromium_src-a7e3ac41cb5b104e6d96fc31c2a1e5330b601ec7.zip chromium_src-a7e3ac41cb5b104e6d96fc31c2a1e5330b601ec7.tar.gz chromium_src-a7e3ac41cb5b104e6d96fc31c2a1e5330b601ec7.tar.bz2 |
cc: Make separate interface for BeginFrame ipc from OutputSurface
Decouple BeginFrame message from OutputSurface and creates new interface.
R=danakj@chromium.org, brianderson@chromium.org, skyostil@chromium.org, piman@chromium.org, boliu@chromium.org
BUG=416760
TEST=cc_unittests, content_unittests
Review URL: https://codereview.chromium.org/619843002
Cr-Commit-Position: refs/heads/master@{#303715}
64 files changed, 999 insertions, 349 deletions
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc index 5af1109..ef98ecb 100644 --- a/android_webview/browser/hardware_renderer.cc +++ b/android_webview/browser/hardware_renderer.cc @@ -17,6 +17,7 @@ #include "cc/layers/layer.h" #include "cc/output/compositor_frame.h" #include "cc/output/output_surface.h" +#include "cc/scheduler/begin_frame_source.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_settings.h" #include "gpu/command_buffer/client/gl_in_process_context.h" @@ -101,7 +102,7 @@ HardwareRenderer::HardwareRenderer(SharedRendererState* state) settings.single_thread_proxy_scheduler = false; layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded( - this, this, NULL, NULL, settings, NULL); + this, this, nullptr, nullptr, settings, nullptr, nullptr); layer_tree_host_->SetRootLayer(root_layer_); layer_tree_host_->SetLayerTreeHostClientReady(); layer_tree_host_->set_has_transparent_background(true); diff --git a/cc/layers/layer_perftest.cc b/cc/layers/layer_perftest.cc index fcd0844..f42e228 100644 --- a/cc/layers/layer_perftest.cc +++ b/cc/layers/layer_perftest.cc @@ -40,7 +40,7 @@ class LayerPerfTest : public testing::Test { virtual void SetUp() override { layer_tree_host_ = FakeLayerTreeHost::Create(&fake_client_); layer_tree_host_->InitializeSingleThreaded( - &fake_client_, base::MessageLoopProxy::current()); + &fake_client_, base::MessageLoopProxy::current(), nullptr); } virtual void TearDown() override { diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc index ecdd916..246a658 100644 --- a/cc/layers/layer_unittest.cc +++ b/cc/layers/layer_unittest.cc @@ -42,7 +42,9 @@ class MockLayerTreeHost : public LayerTreeHost { public: explicit MockLayerTreeHost(FakeLayerTreeHostClient* client) : LayerTreeHost(client, nullptr, nullptr, LayerTreeSettings()) { - InitializeSingleThreaded(client, base::MessageLoopProxy::current()); + InitializeSingleThreaded(client, + base::MessageLoopProxy::current(), + nullptr); } MOCK_METHOD0(SetNeedsCommit, void()); @@ -935,7 +937,8 @@ class LayerTreeHostFactory { shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), LayerTreeSettings(), - base::MessageLoopProxy::current()).Pass(); + base::MessageLoopProxy::current(), + nullptr); } scoped_ptr<LayerTreeHost> Create(LayerTreeSettings settings) { @@ -945,7 +948,8 @@ class LayerTreeHostFactory { shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), settings, - base::MessageLoopProxy::current()).Pass(); + base::MessageLoopProxy::current(), + nullptr); } private: diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc index 25fa708..8a998f3 100644 --- a/cc/layers/scrollbar_layer_unittest.cc +++ b/cc/layers/scrollbar_layer_unittest.cc @@ -632,7 +632,9 @@ class FakeLayerTreeHost : public LayerTreeHost { next_id_(1), total_ui_resource_created_(0), total_ui_resource_deleted_(0) { - InitializeSingleThreaded(client, base::MessageLoopProxy::current()); + InitializeSingleThreaded(client, + base::MessageLoopProxy::current(), + nullptr); } UIResourceId CreateUIResource(UIResourceClient* content) override { diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc index d355b62..f2ee269 100644 --- a/cc/layers/texture_layer_unittest.cc +++ b/cc/layers/texture_layer_unittest.cc @@ -52,7 +52,9 @@ class MockLayerTreeHost : public LayerTreeHost { public: explicit MockLayerTreeHost(FakeLayerTreeHostClient* client) : LayerTreeHost(client, nullptr, nullptr, LayerTreeSettings()) { - InitializeSingleThreaded(client, base::MessageLoopProxy::current()); + InitializeSingleThreaded(client, + base::MessageLoopProxy::current(), + nullptr); } MOCK_METHOD0(SetNeedsCommit, void()); diff --git a/cc/layers/tiled_layer_unittest.cc b/cc/layers/tiled_layer_unittest.cc index 3822241..7433a14 100644 --- a/cc/layers/tiled_layer_unittest.cc +++ b/cc/layers/tiled_layer_unittest.cc @@ -82,7 +82,8 @@ class SynchronousOutputSurfaceLayerTreeHost : public LayerTreeHost { : LayerTreeHost(client, manager, NULL, settings), output_surface_created_(false) { LayerTreeHost::InitializeThreaded(base::MessageLoopProxy::current(), - impl_task_runner); + impl_task_runner, + nullptr); } bool output_surface_created_; diff --git a/cc/layers/ui_resource_layer_unittest.cc b/cc/layers/ui_resource_layer_unittest.cc index 784ff35..09d57a9 100644 --- a/cc/layers/ui_resource_layer_unittest.cc +++ b/cc/layers/ui_resource_layer_unittest.cc @@ -36,7 +36,9 @@ class UIResourceLayerTest : public testing::Test { virtual void SetUp() { layer_tree_host_ = FakeLayerTreeHost::Create(&fake_client_); layer_tree_host_->InitializeSingleThreaded( - &fake_client_, base::MessageLoopProxy::current()); + &fake_client_, + base::MessageLoopProxy::current(), + nullptr); } virtual void TearDown() { diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h index 0a0d456..04bd4a3 100644 --- a/cc/output/output_surface.h +++ b/cc/output/output_surface.h @@ -125,11 +125,6 @@ class CC_EXPORT OutputSurface { // processing should be stopped, or lowered in priority. virtual void UpdateSmoothnessTakesPriority(bool prefer_smoothness) {} - // Requests a BeginFrame notification from the output surface. The - // notification will be delivered by calling - // OutputSurfaceClient::BeginFrame until the callback is disabled. - virtual void SetNeedsBeginFrame(bool enable) {} - bool HasClient() { return !!client_; } // Get the class capable of informing cc of hardware overlay capability. diff --git a/cc/output/output_surface_client.h b/cc/output/output_surface_client.h index 99b174b..60750b4 100644 --- a/cc/output/output_surface_client.h +++ b/cc/output/output_surface_client.h @@ -9,7 +9,6 @@ #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "cc/base/cc_export.h" -#include "cc/output/begin_frame_args.h" #include "cc/output/context_provider.h" #include "ui/gfx/geometry/rect.h" @@ -33,7 +32,6 @@ class CC_EXPORT OutputSurfaceClient { virtual void CommitVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval) = 0; virtual void SetNeedsRedrawRect(const gfx::Rect& damage_rect) = 0; - virtual void BeginFrame(const BeginFrameArgs& args) = 0; virtual void DidSwapBuffers() = 0; virtual void DidSwapBuffersComplete() = 0; virtual void ReclaimResources(const CompositorFrameAck* ack) = 0; diff --git a/cc/output/output_surface_unittest.cc b/cc/output/output_surface_unittest.cc index b1f4149..4336f07 100644 --- a/cc/output/output_surface_unittest.cc +++ b/cc/output/output_surface_unittest.cc @@ -49,10 +49,6 @@ class TestOutputSurface : public OutputSurface { CommitVSyncParameters(timebase, interval); } - void BeginFrameForTesting() { - client_->BeginFrame(CreateExpiredBeginFrameArgsForTesting()); - } - void DidSwapBuffersForTesting() { client_->DidSwapBuffers(); } void OnSwapBuffersCompleteForTesting() { client_->DidSwapBuffersComplete(); } diff --git a/cc/scheduler/begin_frame_source.cc b/cc/scheduler/begin_frame_source.cc index 4a9f184..dd6cdbe 100644 --- a/cc/scheduler/begin_frame_source.cc +++ b/cc/scheduler/begin_frame_source.cc @@ -79,9 +79,9 @@ void BeginFrameSourceMixIn::SetNeedsBeginFrames(bool needs_begin_frames) { "new state", needs_begin_frames); if (needs_begin_frames_ != needs_begin_frames) { + needs_begin_frames_ = needs_begin_frames; OnNeedsBeginFramesChange(needs_begin_frames); } - needs_begin_frames_ = needs_begin_frames; } void BeginFrameSourceMixIn::AddObserver(BeginFrameObserver* obs) { diff --git a/cc/scheduler/begin_frame_source.h b/cc/scheduler/begin_frame_source.h index 3d849a4..28359d3 100644 --- a/cc/scheduler/begin_frame_source.h +++ b/cc/scheduler/begin_frame_source.h @@ -117,6 +117,9 @@ class CC_EXPORT BeginFrameSource { virtual void AddObserver(BeginFrameObserver* obs) = 0; virtual void RemoveObserver(BeginFrameObserver* obs) = 0; + // Tells the Source that client is ready to handle BeginFrames messages. + virtual void SetClientReady() = 0; + // Tracing support - Recommend (but not required) to call this implementation // in any override. virtual void AsValueInto(base::debug::TracedValue* dict) const = 0; @@ -137,8 +140,9 @@ class CC_EXPORT BeginFrameSourceMixIn : public BeginFrameSource { bool NeedsBeginFrames() const override; void SetNeedsBeginFrames(bool needs_begin_frames) override; void DidFinishFrame(size_t remaining_frames) override {} - void AddObserver(BeginFrameObserver* obs) override; - void RemoveObserver(BeginFrameObserver* obs) override; + void AddObserver(BeginFrameObserver* obs) final; + void RemoveObserver(BeginFrameObserver* obs) final; + void SetClientReady() override {} // Tracing support - Recommend (but not required) to call this implementation // in any override. diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index 2a86d4b..9ed3d72 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc @@ -5,6 +5,7 @@ #include "cc/scheduler/scheduler.h" #include <algorithm> + #include "base/auto_reset.h" #include "base/debug/trace_event.h" #include "base/debug/trace_event_argument.h" @@ -32,8 +33,10 @@ BeginFrameSource* SchedulerFrameSourcesConstructor::ConstructPrimaryFrameSource( TRACE_EVENT1("cc", "Scheduler::Scheduler()", "PrimaryFrameSource", - "SchedulerClient"); - return scheduler->client_->ExternalBeginFrameSource(); + "ExternalBeginFrameSource"); + DCHECK(scheduler->primary_frame_source_internal_) + << "Need external BeginFrameSource"; + return scheduler->primary_frame_source_internal_.get(); } else { TRACE_EVENT1("cc", "Scheduler::Scheduler()", @@ -74,11 +77,12 @@ Scheduler::Scheduler( int layer_tree_host_id, const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, base::PowerMonitor* power_monitor, + scoped_ptr<BeginFrameSource> external_begin_frame_source, SchedulerFrameSourcesConstructor* frame_sources_constructor) : frame_source_(), primary_frame_source_(NULL), background_frame_source_(NULL), - primary_frame_source_internal_(), + primary_frame_source_internal_(external_begin_frame_source.Pass()), background_frame_source_internal_(), vsync_observer_(NULL), settings_(scheduler_settings), @@ -114,6 +118,7 @@ Scheduler::Scheduler( primary_frame_source_ = frame_sources_constructor->ConstructPrimaryFrameSource(this); frame_source_->AddSource(primary_frame_source_); + primary_frame_source_->SetClientReady(); // Background ticking frame source background_frame_source_ = @@ -125,6 +130,8 @@ Scheduler::Scheduler( Scheduler::~Scheduler() { TeardownPowerMonitoring(); + if (frame_source_->NeedsBeginFrames()) + frame_source_->SetNeedsBeginFrames(false); } base::TimeTicks Scheduler::Now() const { diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h index abbfcb7..523c246 100644 --- a/cc/scheduler/scheduler.h +++ b/cc/scheduler/scheduler.h @@ -34,7 +34,6 @@ namespace cc { class SchedulerClient { public: - virtual BeginFrameSource* ExternalBeginFrameSource() = 0; virtual void WillBeginImplFrame(const BeginFrameArgs& args) = 0; virtual void ScheduledActionSendBeginMainFrame() = 0; virtual DrawResult ScheduledActionDrawAndSwapIfPossible() = 0; @@ -81,13 +80,15 @@ class CC_EXPORT Scheduler : public BeginFrameObserverMixIn, const SchedulerSettings& scheduler_settings, int layer_tree_host_id, const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - base::PowerMonitor* power_monitor) { + base::PowerMonitor* power_monitor, + scoped_ptr<BeginFrameSource> external_begin_frame_source) { SchedulerFrameSourcesConstructor frame_sources_constructor; return make_scoped_ptr(new Scheduler(client, scheduler_settings, layer_tree_host_id, task_runner, power_monitor, + external_begin_frame_source.Pass(), &frame_sources_constructor)); } @@ -174,6 +175,7 @@ class CC_EXPORT Scheduler : public BeginFrameObserverMixIn, int layer_tree_host_id, const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, base::PowerMonitor* power_monitor, + scoped_ptr<BeginFrameSource> external_begin_frame_source, SchedulerFrameSourcesConstructor* frame_sources_constructor); // virtual for testing - Don't call these in the constructor or diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index 7da6267..61de1b8 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc @@ -47,13 +47,11 @@ void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler, class FakeSchedulerClient : public SchedulerClient { public: - struct FakeBeginFrameSourceForFakeSchedulerClient - : public FakeBeginFrameSource { - FakeSchedulerClient* client_; - - explicit FakeBeginFrameSourceForFakeSchedulerClient( - FakeSchedulerClient* client) + class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn { + public: + explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client) : client_(client) {} + virtual ~FakeExternalBeginFrameSource() {} void OnNeedsBeginFramesChange(bool needs_begin_frames) override { if (needs_begin_frames) { @@ -63,6 +61,13 @@ class FakeSchedulerClient : public SchedulerClient { } client_->states_.push_back(client_->scheduler_->AsValue()); } + + void TestOnBeginFrame(const BeginFrameArgs& args) { + return CallOnBeginFrame(args); + } + + private: + FakeSchedulerClient* client_; }; class FakePowerMonitorSource : public base::PowerMonitorSource { @@ -86,7 +91,7 @@ class FakeSchedulerClient : public SchedulerClient { redraw_will_happen_if_update_visible_tiles_happens_(false), now_src_(TestNowSource::Create()), task_runner_(new OrderedSimpleTaskRunner(now_src_, true)), - fake_frame_source_(this), + fake_external_begin_frame_source_(nullptr), fake_power_monitor_source_(new FakePowerMonitorSource), power_monitor_(make_scoped_ptr<base::PowerMonitorSource>( fake_power_monitor_source_)), @@ -108,8 +113,21 @@ class FakeSchedulerClient : public SchedulerClient { } TestScheduler* CreateScheduler(const SchedulerSettings& settings) { - scheduler_ = TestScheduler::Create( - now_src_, this, settings, 0, task_runner_, &power_monitor_); + scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source; + if (settings.begin_frame_scheduling_enabled && + settings.throttle_frame_production) { + fake_external_begin_frame_source.reset( + new FakeExternalBeginFrameSource(this)); + fake_external_begin_frame_source_ = + fake_external_begin_frame_source.get(); + } + scheduler_ = TestScheduler::Create(now_src_, + this, + settings, + 0, + task_runner_, + &power_monitor_, + fake_external_begin_frame_source.Pass()); DCHECK(scheduler_); return scheduler_.get(); } @@ -119,7 +137,10 @@ class FakeSchedulerClient : public SchedulerClient { void set_log_anticipated_draw_time_change(bool log) { log_anticipated_draw_time_change_ = log; } - bool needs_begin_frames() { return fake_frame_source_.NeedsBeginFrames(); } + bool needs_begin_frames() { + DCHECK(ExternalBeginFrame()); + return fake_external_begin_frame_source_->NeedsBeginFrames(); + } int num_draws() const { return num_draws_; } int num_actions_() const { return static_cast<int>(actions_.size()); } const char* Action(int i) const { return actions_[i]; } @@ -132,8 +153,9 @@ class FakeSchedulerClient : public SchedulerClient { return scheduler_->settings().begin_frame_scheduling_enabled && scheduler_->settings().throttle_frame_production; } - FakeBeginFrameSource* ExternalBeginFrameSource() override { - return &fake_frame_source_; + + FakeExternalBeginFrameSource* fake_external_begin_frame_source() const { + return fake_external_begin_frame_source_; } base::PowerMonitor* PowerMonitor() { return &power_monitor_; } @@ -145,12 +167,11 @@ class FakeSchedulerClient : public SchedulerClient { void AdvanceFrame() { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "FakeSchedulerClient::AdvanceFrame"); - // EXPECT_TRUE(needs_begin_frames()); if (ExternalBeginFrame()) { // Creep the time forward so that any BeginFrameArgs is not equal to the // last one otherwise we violate the BeginFrameSource contract. now_src_->AdvanceNowMicroseconds(1); - fake_frame_source_.TestOnBeginFrame( + fake_external_begin_frame_source_->TestOnBeginFrame( CreateBeginFrameArgsForTesting(now_src_)); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); } @@ -288,7 +309,7 @@ class FakeSchedulerClient : public SchedulerClient { std::vector<scoped_refptr<base::debug::ConvertableToTraceFormat>> states_; scoped_refptr<TestNowSource> now_src_; scoped_refptr<OrderedSimpleTaskRunner> task_runner_; - FakeBeginFrameSourceForFakeSchedulerClient fake_frame_source_; + FakeExternalBeginFrameSource* fake_external_begin_frame_source_; FakePowerMonitorSource* fake_power_monitor_source_; base::PowerMonitor power_monitor_; scoped_ptr<TestScheduler> scheduler_; @@ -327,8 +348,6 @@ void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler, EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); client->task_runner().RunTasksWhile(client->ImplFrameDeadlinePending(true)); EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); - - // EXPECT_FALSE(client->needs_begin_frames()); } TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) { @@ -1179,7 +1198,7 @@ TEST(SchedulerTest, PollForCommitCompletion) { BeginFrameArgs frame_args = CreateBeginFrameArgsForTesting(client.now_src()); frame_args.interval = base::TimeDelta::FromMilliseconds(1000); - client.ExternalBeginFrameSource()->TestOnBeginFrame(frame_args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(frame_args); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); client.task_runner().RunPendingTasks(); // Run posted deadline. @@ -1192,7 +1211,7 @@ TEST(SchedulerTest, PollForCommitCompletion) { // the NotifyReadyToCommit for now. EXPECT_FALSE(scheduler->CommitPending()); scheduler->SetNeedsCommit(); - client.ExternalBeginFrameSource()->TestOnBeginFrame(frame_args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(frame_args); EXPECT_TRUE(scheduler->CommitPending()); // Draw and swap the frame, but don't ack the swap to simulate the Browser @@ -1251,7 +1270,7 @@ TEST(SchedulerTest, BeginRetroFrame) { // This is the first BeginFrame, which will be handled immediately. BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src()); args.deadline += base::TimeDelta::FromHours(1); - client.ExternalBeginFrameSource()->TestOnBeginFrame(args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(args); EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); @@ -1260,9 +1279,9 @@ TEST(SchedulerTest, BeginRetroFrame) { // Queue BeginFrames while we are still handling the previous BeginFrame. args.frame_time += base::TimeDelta::FromSeconds(1); - client.ExternalBeginFrameSource()->TestOnBeginFrame(args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(args); args.frame_time += base::TimeDelta::FromSeconds(1); - client.ExternalBeginFrameSource()->TestOnBeginFrame(args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(args); // If we don't swap on the deadline, we wait for the next BeginImplFrame. client.task_runner().RunPendingTasks(); // Run posted deadline. @@ -1328,7 +1347,7 @@ TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) { // This is the first BeginFrame, which will be handled immediately. BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src()); args.deadline += base::TimeDelta::FromHours(1); - client.ExternalBeginFrameSource()->TestOnBeginFrame(args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(args); EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); @@ -1338,7 +1357,7 @@ TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) { // Queue BeginFrame while we are still handling the previous BeginFrame. EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); args.frame_time += base::TimeDelta::FromSeconds(1); - client.ExternalBeginFrameSource()->TestOnBeginFrame(args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(args); EXPECT_NO_ACTION(client); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); client.Reset(); @@ -1369,7 +1388,7 @@ TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) { // Queue BeginFrame while we are still handling the previous BeginFrame. args.frame_time += base::TimeDelta::FromSeconds(1); - client.ExternalBeginFrameSource()->TestOnBeginFrame(args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(args); EXPECT_NO_ACTION(client); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); EXPECT_TRUE(client.needs_begin_frames()); @@ -1408,11 +1427,12 @@ void BeginFramesNotFromClient(bool begin_frame_scheduling_enabled, scheduler->SetCanDraw(true); InitializeOutputSurfaceAndFirstCommit(scheduler, &client); + DCHECK(!client.fake_external_begin_frame_source()); + // SetNeedsCommit should begin the frame on the next BeginImplFrame // without calling SetNeedsBeginFrame. client.Reset(); scheduler->SetNeedsCommit(); - EXPECT_FALSE(client.needs_begin_frames()); EXPECT_NO_ACTION(client); client.Reset(); @@ -1422,21 +1442,18 @@ void BeginFramesNotFromClient(bool begin_frame_scheduling_enabled, EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); - EXPECT_FALSE(client.needs_begin_frames()); client.Reset(); // If we don't swap on the deadline, we wait for the next BeginFrame. client.task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_NO_ACTION(client); EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); - EXPECT_FALSE(client.needs_begin_frames()); client.Reset(); // NotifyReadyToCommit should trigger the commit. scheduler->NotifyBeginMainFrameStarted(); scheduler->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); - EXPECT_FALSE(client.needs_begin_frames()); client.Reset(); // BeginImplFrame should prepare the draw. @@ -1444,14 +1461,12 @@ void BeginFramesNotFromClient(bool begin_frame_scheduling_enabled, EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); - EXPECT_FALSE(client.needs_begin_frames()); client.Reset(); // BeginImplFrame deadline should draw. client.task_runner().RunTasksWhile(client.ImplFrameDeadlinePending(true)); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1); EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); - EXPECT_FALSE(client.needs_begin_frames()); client.Reset(); // The following BeginImplFrame deadline should SetNeedsBeginFrame(false) @@ -1465,7 +1480,6 @@ void BeginFramesNotFromClient(bool begin_frame_scheduling_enabled, // when the BeginFrame is no longer needed. client.task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_NO_ACTION(client); - EXPECT_FALSE(client.needs_begin_frames()); client.Reset(); } @@ -1503,6 +1517,8 @@ void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled, scheduler->SetCanDraw(true); InitializeOutputSurfaceAndFirstCommit(scheduler, &client); + DCHECK(!client.fake_external_begin_frame_source()); + // To test swap ack throttling, this test disables automatic swap acks. scheduler->SetMaxSwapsPending(1); client.SetAutomaticSwapAck(false); @@ -1510,7 +1526,6 @@ void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled, // SetNeedsCommit should begin the frame on the next BeginImplFrame. client.Reset(); scheduler->SetNeedsCommit(); - EXPECT_FALSE(client.needs_begin_frames()); EXPECT_NO_ACTION(client); client.Reset(); @@ -1519,14 +1534,12 @@ void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled, EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); - EXPECT_FALSE(client.needs_begin_frames()); client.Reset(); // NotifyReadyToCommit should trigger the pending commit and draw. scheduler->NotifyBeginMainFrameStarted(); scheduler->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); - EXPECT_FALSE(client.needs_begin_frames()); client.Reset(); // Swapping will put us into a swap throttled state. @@ -1534,7 +1547,6 @@ void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled, EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); - EXPECT_FALSE(client.needs_begin_frames()); client.Reset(); // While swap throttled, BeginFrames should trigger BeginImplFrames, @@ -1543,14 +1555,12 @@ void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled, client.task_runner().RunPendingTasks(); // Run posted BeginFrame. EXPECT_ACTION("WillBeginImplFrame", client, 0, 1); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); - EXPECT_FALSE(client.needs_begin_frames()); client.Reset(); // Take us out of a swap throttled state. scheduler->DidSwapBuffersComplete(); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); - EXPECT_FALSE(client.needs_begin_frames()); client.Reset(); // BeginImplFrame deadline should draw. @@ -1559,7 +1569,6 @@ void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled, EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); - EXPECT_FALSE(client.needs_begin_frames()); client.Reset(); } @@ -1806,7 +1815,7 @@ TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) { client.Reset(); BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src()); args.deadline += base::TimeDelta::FromHours(1); - client.ExternalBeginFrameSource()->TestOnBeginFrame(args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(args); EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); @@ -1814,9 +1823,9 @@ TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) { // Queue BeginFrames while we are still handling the previous BeginFrame. args.frame_time += base::TimeDelta::FromSeconds(1); - client.ExternalBeginFrameSource()->TestOnBeginFrame(args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(args); args.frame_time += base::TimeDelta::FromSeconds(1); - client.ExternalBeginFrameSource()->TestOnBeginFrame(args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(args); // If we don't swap on the deadline, we wait for the next BeginImplFrame. client.Reset(); @@ -1864,7 +1873,7 @@ TEST(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) { client.Reset(); BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src()); args.deadline += base::TimeDelta::FromHours(1); - client.ExternalBeginFrameSource()->TestOnBeginFrame(args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(args); EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); @@ -1872,9 +1881,9 @@ TEST(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) { // Queue BeginFrames while we are still handling the previous BeginFrame. args.frame_time += base::TimeDelta::FromSeconds(1); - client.ExternalBeginFrameSource()->TestOnBeginFrame(args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(args); args.frame_time += base::TimeDelta::FromSeconds(1); - client.ExternalBeginFrameSource()->TestOnBeginFrame(args); + client.fake_external_begin_frame_source()->TestOnBeginFrame(args); // If we don't swap on the deadline, we wait for the next BeginImplFrame. client.Reset(); diff --git a/cc/surfaces/display.h b/cc/surfaces/display.h index 5f80d64..5935534 100644 --- a/cc/surfaces/display.h +++ b/cc/surfaces/display.h @@ -63,7 +63,6 @@ class CC_SURFACES_EXPORT Display : public OutputSurfaceClient, void CommitVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval) override; void SetNeedsRedrawRect(const gfx::Rect& damage_rect) override {} - void BeginFrame(const BeginFrameArgs& args) override {} void DidSwapBuffers() override; void DidSwapBuffersComplete() override; void ReclaimResources(const CompositorFrameAck* ack) override {} diff --git a/cc/test/fake_output_surface.cc b/cc/test/fake_output_surface.cc index df9c0f7..46efba0 100644 --- a/cc/test/fake_output_surface.cc +++ b/cc/test/fake_output_surface.cc @@ -20,9 +20,7 @@ FakeOutputSurface::FakeOutputSurface( : OutputSurface(context_provider), client_(NULL), num_sent_frames_(0), - needs_begin_frame_(false), - has_external_stencil_test_(false), - fake_weak_ptr_factory_(this) { + has_external_stencil_test_(false) { if (delegated_rendering) { capabilities_.delegated_rendering = true; capabilities_.max_frames_pending = 1; @@ -35,8 +33,7 @@ FakeOutputSurface::FakeOutputSurface( : OutputSurface(software_device.Pass()), client_(NULL), num_sent_frames_(0), - has_external_stencil_test_(false), - fake_weak_ptr_factory_(this) { + has_external_stencil_test_(false) { if (delegated_rendering) { capabilities_.delegated_rendering = true; capabilities_.max_frames_pending = 1; @@ -50,8 +47,7 @@ FakeOutputSurface::FakeOutputSurface( : OutputSurface(context_provider, software_device.Pass()), client_(NULL), num_sent_frames_(0), - has_external_stencil_test_(false), - fake_weak_ptr_factory_(this) { + has_external_stencil_test_(false) { if (delegated_rendering) { capabilities_.delegated_rendering = true; capabilities_.max_frames_pending = 1; @@ -82,24 +78,6 @@ void FakeOutputSurface::SwapBuffers(CompositorFrame* frame) { client_->DidSwapBuffers(); } -void FakeOutputSurface::SetNeedsBeginFrame(bool enable) { - needs_begin_frame_ = enable; - OutputSurface::SetNeedsBeginFrame(enable); - - if (enable) { - base::MessageLoop::current()->PostDelayedTask( - FROM_HERE, - base::Bind(&FakeOutputSurface::OnBeginFrame, - fake_weak_ptr_factory_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(16)); - } -} - -void FakeOutputSurface::OnBeginFrame() { - client_->BeginFrame(CreateBeginFrameArgsForTesting()); -} - - bool FakeOutputSurface::BindToClient(OutputSurfaceClient* client) { if (OutputSurface::BindToClient(client)) { client_ = client; diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h index 59c9a8c..f28fccc 100644 --- a/cc/test/fake_output_surface.h +++ b/cc/test/fake_output_surface.h @@ -94,9 +94,6 @@ class FakeOutputSurface : public OutputSurface { void SwapBuffers(CompositorFrame* frame) override; - void SetNeedsBeginFrame(bool enable) override; - bool needs_begin_frame() const { return needs_begin_frame_; } - bool BindToClient(OutputSurfaceClient* client) override; using OutputSurface::ReleaseGL; @@ -137,18 +134,13 @@ class FakeOutputSurface : public OutputSurface { scoped_ptr<SoftwareOutputDevice> software_device, bool delegated_rendering); - void OnBeginFrame(); - OutputSurfaceClient* client_; CompositorFrame last_sent_frame_; size_t num_sent_frames_; - bool needs_begin_frame_; bool has_external_stencil_test_; TransferableResourceArray resources_held_by_parent_; scoped_ptr<ManagedMemoryPolicy> memory_policy_to_set_at_bind_; gfx::Rect last_swap_rect_; - - base::WeakPtrFactory<FakeOutputSurface> fake_weak_ptr_factory_; }; } // namespace cc diff --git a/cc/test/fake_output_surface_client.cc b/cc/test/fake_output_surface_client.cc index 77c7f8a..073a29f 100644 --- a/cc/test/fake_output_surface_client.cc +++ b/cc/test/fake_output_surface_client.cc @@ -16,10 +16,6 @@ void FakeOutputSurfaceClient::ReleaseGL() { output_surface_->ReleaseContextProvider(); } -void FakeOutputSurfaceClient::BeginFrame(const BeginFrameArgs& args) { - begin_frame_count_++; -} - void FakeOutputSurfaceClient::DidSwapBuffers() { swap_count_++; } diff --git a/cc/test/fake_output_surface_client.h b/cc/test/fake_output_surface_client.h index a7620b6..310842d 100644 --- a/cc/test/fake_output_surface_client.h +++ b/cc/test/fake_output_surface_client.h @@ -16,7 +16,6 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient { public: FakeOutputSurfaceClient() : output_surface_(NULL), - begin_frame_count_(0), swap_count_(0), deferred_initialize_called_(false), did_lose_output_surface_called_(false), @@ -24,7 +23,6 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient { explicit FakeOutputSurfaceClient(OutputSurface* output_surface) : output_surface_(output_surface), - begin_frame_count_(0), swap_count_(0), deferred_initialize_called_(false), did_lose_output_surface_called_(false), @@ -35,7 +33,6 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient { void CommitVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval) override {} void SetNeedsRedrawRect(const gfx::Rect& damage_rect) override {} - void BeginFrame(const BeginFrameArgs& args) override; void DidSwapBuffers() override; void DidSwapBuffersComplete() override {} void ReclaimResources(const CompositorFrameAck* ack) override {} @@ -50,7 +47,6 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient { void SetMemoryPolicy(const ManagedMemoryPolicy& policy) override; void SetTreeActivationCallback(const base::Closure&) override {} - int begin_frame_count() { return begin_frame_count_; } int swap_count() { return swap_count_; } bool deferred_initialize_called() { @@ -65,7 +61,6 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient { private: OutputSurface* output_surface_; - int begin_frame_count_; int swap_count_; bool deferred_initialize_called_; bool did_lose_output_surface_called_; diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index b17c1e5..806a5b3 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc @@ -15,6 +15,7 @@ #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" #include "cc/test/animation_test_common.h" +#include "cc/test/begin_frame_args_test.h" #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_output_surface.h" #include "cc/test/test_context_provider.h" @@ -53,6 +54,52 @@ void TestHooks::CreateResourceAndRasterWorkerPool( raster_worker_pool, resource_pool, staging_resource_pool); } +class ExternalBeginFrameSourceForTest + : public BeginFrameSourceMixIn, + public NON_EXPORTED_BASE(base::NonThreadSafe) { + public: + explicit ExternalBeginFrameSourceForTest(double refresh_rate) + : milliseconds_per_frame_(1000.0 / refresh_rate), + is_ready_(false), + weak_ptr_factory_(this) { + DetachFromThread(); + } + + virtual ~ExternalBeginFrameSourceForTest() { + DCHECK(CalledOnValidThread()); + } + + virtual void OnNeedsBeginFramesChange(bool needs_begin_frames) override { + DCHECK(CalledOnValidThread()); + if (needs_begin_frames) { + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&ExternalBeginFrameSourceForTest::TestOnBeginFrame, + weak_ptr_factory_.GetWeakPtr()), + base::TimeDelta::FromMilliseconds(milliseconds_per_frame_)); + } + } + + virtual void SetClientReady() override { + DCHECK(CalledOnValidThread()); + is_ready_ = true; + } + + bool is_ready() const { + return is_ready_; + } + + void TestOnBeginFrame() { + DCHECK(CalledOnValidThread()); + CallOnBeginFrame(CreateBeginFrameArgsForTesting()); + } + + private: + double milliseconds_per_frame_; + bool is_ready_; + base::WeakPtrFactory<ExternalBeginFrameSourceForTest> weak_ptr_factory_; +}; + // Adapts ThreadProxy for test. Injects test hooks for testing. class ThreadProxyForTest : public ThreadProxy { public: @@ -60,9 +107,14 @@ class ThreadProxyForTest : public ThreadProxy { TestHooks* test_hooks, LayerTreeHost* host, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) { + scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) { return make_scoped_ptr(new ThreadProxyForTest( - test_hooks, host, main_task_runner, impl_task_runner)); + test_hooks, + host, + main_task_runner, + impl_task_runner, + external_begin_frame_source.Pass())); } ~ThreadProxyForTest() override {} @@ -105,8 +157,11 @@ class ThreadProxyForTest : public ThreadProxy { TestHooks* test_hooks, LayerTreeHost* host, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) - : ThreadProxy(host, main_task_runner, impl_task_runner), + scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) + : ThreadProxy(host, main_task_runner, + impl_task_runner, + external_begin_frame_source.Pass()), test_hooks_(test_hooks) {} }; @@ -360,7 +415,8 @@ class LayerTreeHostForTesting : public LayerTreeHost { LayerTreeHostClientForTesting* client, const LayerTreeSettings& settings, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) { + scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) { scoped_ptr<LayerTreeHostForTesting> layer_tree_host( new LayerTreeHostForTesting(test_hooks, client, settings)); if (impl_task_runner.get()) { @@ -368,10 +424,14 @@ class LayerTreeHostForTesting : public LayerTreeHost { ThreadProxyForTest::Create(test_hooks, layer_tree_host.get(), main_task_runner, - impl_task_runner)); + impl_task_runner, + external_begin_frame_source.Pass())); } else { layer_tree_host->InitializeForTesting(SingleThreadProxy::Create( - layer_tree_host.get(), client, main_task_runner)); + layer_tree_host.get(), + client, + main_task_runner, + external_begin_frame_source.Pass())); } return layer_tree_host.Pass(); } @@ -416,6 +476,7 @@ class LayerTreeHostForTesting : public LayerTreeHost { LayerTreeTest::LayerTreeTest() : output_surface_(nullptr), + external_begin_frame_source_(nullptr), beginning_(false), end_when_begin_returns_(false), timed_out_(false), @@ -545,13 +606,22 @@ void LayerTreeTest::WillBeginTest() { void LayerTreeTest::DoBeginTest() { client_ = LayerTreeHostClientForTesting::Create(this); + scoped_ptr<ExternalBeginFrameSourceForTest> external_begin_frame_source; + if (settings_.begin_frame_scheduling_enabled && + settings_.throttle_frame_production) { + external_begin_frame_source.reset( + new ExternalBeginFrameSourceForTest(settings_.refresh_rate)); + external_begin_frame_source_ = external_begin_frame_source.get(); + } + DCHECK(!impl_thread_ || impl_thread_->message_loop_proxy().get()); layer_tree_host_ = LayerTreeHostForTesting::Create( this, client_.get(), settings_, base::MessageLoopProxy::current(), - impl_thread_ ? impl_thread_->message_loop_proxy() : NULL); + impl_thread_ ? impl_thread_->message_loop_proxy() : NULL, + external_begin_frame_source.Pass()); ASSERT_TRUE(layer_tree_host_); started_ = true; @@ -720,6 +790,12 @@ scoped_ptr<OutputSurface> LayerTreeTest::CreateOutputSurface(bool fallback) { output_surface->capabilities().delegated_rendering); } output_surface_ = output_surface.get(); + + if (settings_.begin_frame_scheduling_enabled && + settings_.throttle_frame_production) { + DCHECK(external_begin_frame_source_); + DCHECK(external_begin_frame_source_->is_ready()); + } return output_surface.Pass(); } diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h index 065be18..531e28d 100644 --- a/cc/test/layer_tree_test.h +++ b/cc/test/layer_tree_test.h @@ -17,6 +17,7 @@ class WebGraphicsContext3D; } namespace cc { +class ExternalBeginFrameSourceForTest; class FakeLayerTreeHostClient; class FakeOutputSurface; class LayerImpl; @@ -210,6 +211,7 @@ class LayerTreeTest : public testing::Test, public TestHooks { scoped_ptr<LayerTreeHostClientForTesting> client_; scoped_ptr<LayerTreeHost> layer_tree_host_; FakeOutputSurface* output_surface_; + ExternalBeginFrameSourceForTest* external_begin_frame_source_; bool beginning_; bool end_when_begin_returns_; diff --git a/cc/test/scheduler_test_common.cc b/cc/test/scheduler_test_common.cc index ef4cefd..1f87991 100644 --- a/cc/test/scheduler_test_common.cc +++ b/cc/test/scheduler_test_common.cc @@ -128,12 +128,14 @@ TestScheduler::TestScheduler( int layer_tree_host_id, const scoped_refptr<OrderedSimpleTaskRunner>& test_task_runner, base::PowerMonitor* power_monitor, - TestSchedulerFrameSourcesConstructor* frame_sources_constructor) + TestSchedulerFrameSourcesConstructor* frame_sources_constructor, + scoped_ptr<BeginFrameSource> external_begin_frame_source) : Scheduler(client, scheduler_settings, layer_tree_host_id, test_task_runner, power_monitor, + external_begin_frame_source.Pass(), frame_sources_constructor), now_src_(now_src) { } diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h index d9cb3cf..ea6b2ef 100644 --- a/cc/test/scheduler_test_common.h +++ b/cc/test/scheduler_test_common.h @@ -162,16 +162,19 @@ class TestScheduler : public Scheduler { const SchedulerSettings& scheduler_settings, int layer_tree_host_id, const scoped_refptr<OrderedSimpleTaskRunner>& task_runner, - base::PowerMonitor* power_monitor) { + base::PowerMonitor* power_monitor, + scoped_ptr<BeginFrameSource> external_begin_frame_source) { TestSchedulerFrameSourcesConstructor frame_sources_constructor( task_runner.get(), now_src.get()); - return make_scoped_ptr(new TestScheduler(now_src, - client, - scheduler_settings, - layer_tree_host_id, - task_runner, - power_monitor, - &frame_sources_constructor)); + return make_scoped_ptr(new TestScheduler( + now_src, + client, + scheduler_settings, + layer_tree_host_id, + task_runner, + power_monitor, + &frame_sources_constructor, + external_begin_frame_source.Pass())); } // Extra test helper functionality @@ -195,7 +198,8 @@ class TestScheduler : public Scheduler { int layer_tree_host_id, const scoped_refptr<OrderedSimpleTaskRunner>& test_task_runner, base::PowerMonitor* power_monitor, - TestSchedulerFrameSourcesConstructor* frame_sources_constructor); + TestSchedulerFrameSourcesConstructor* frame_sources_constructor, + scoped_ptr<BeginFrameSource> external_begin_frame_source); scoped_refptr<TestNowSource> now_src_; }; diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index ae85fc7c..f85d4e7 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc @@ -32,6 +32,7 @@ #include "cc/layers/render_surface.h" #include "cc/resources/prioritized_resource_manager.h" #include "cc/resources/ui_resource_request.h" +#include "cc/scheduler/begin_frame_source.h" #include "cc/trees/layer_tree_host_client.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_host_impl.h" @@ -71,12 +72,15 @@ scoped_ptr<LayerTreeHost> LayerTreeHost::CreateThreaded( gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, const LayerTreeSettings& settings, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) { + scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) { DCHECK(main_task_runner.get()); DCHECK(impl_task_runner.get()); scoped_ptr<LayerTreeHost> layer_tree_host(new LayerTreeHost( client, shared_bitmap_manager, gpu_memory_buffer_manager, settings)); - layer_tree_host->InitializeThreaded(main_task_runner, impl_task_runner); + layer_tree_host->InitializeThreaded(main_task_runner, + impl_task_runner, + external_begin_frame_source.Pass()); return layer_tree_host.Pass(); } @@ -86,11 +90,13 @@ scoped_ptr<LayerTreeHost> LayerTreeHost::CreateSingleThreaded( SharedBitmapManager* shared_bitmap_manager, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, const LayerTreeSettings& settings, - scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) { + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) { scoped_ptr<LayerTreeHost> layer_tree_host(new LayerTreeHost( client, shared_bitmap_manager, gpu_memory_buffer_manager, settings)); layer_tree_host->InitializeSingleThreaded(single_thread_client, - main_task_runner); + main_task_runner, + external_begin_frame_source.Pass()); return layer_tree_host.Pass(); } @@ -139,16 +145,23 @@ LayerTreeHost::LayerTreeHost( void LayerTreeHost::InitializeThreaded( scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) { - InitializeProxy( - ThreadProxy::Create(this, main_task_runner, impl_task_runner)); + scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) { + InitializeProxy(ThreadProxy::Create(this, + main_task_runner, + impl_task_runner, + external_begin_frame_source.Pass())); } void LayerTreeHost::InitializeSingleThreaded( LayerTreeHostSingleThreadClient* single_thread_client, - scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) { + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) { InitializeProxy( - SingleThreadProxy::Create(this, single_thread_client, main_task_runner)); + SingleThreadProxy::Create(this, + single_thread_client, + main_task_runner, + external_begin_frame_source.Pass())); } void LayerTreeHost::InitializeForTesting(scoped_ptr<Proxy> proxy_for_testing) { diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index a56a6cd..7820cc2 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h @@ -48,6 +48,7 @@ class GpuMemoryBufferManager; namespace cc { class AnimationRegistrar; +class BeginFrameSource; class HeadsUpDisplayLayer; class Layer; class LayerTreeHostImpl; @@ -92,7 +93,8 @@ class CC_EXPORT LayerTreeHost { gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, const LayerTreeSettings& settings, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source); static scoped_ptr<LayerTreeHost> CreateSingleThreaded( LayerTreeHostClient* client, @@ -100,7 +102,8 @@ class CC_EXPORT LayerTreeHost { SharedBitmapManager* shared_bitmap_manager, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, const LayerTreeSettings& settings, - scoped_refptr<base::SingleThreadTaskRunner> main_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source); virtual ~LayerTreeHost(); void SetLayerTreeHostClientReady(); @@ -318,10 +321,12 @@ class CC_EXPORT LayerTreeHost { const LayerTreeSettings& settings); void InitializeThreaded( scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source); void InitializeSingleThreaded( LayerTreeHostSingleThreadClient* single_thread_client, - scoped_refptr<base::SingleThreadTaskRunner> main_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source); void InitializeForTesting(scoped_ptr<Proxy> proxy_for_testing); void SetOutputSurfaceLostForTesting(bool is_lost) { output_surface_lost_ = is_lost; diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 6512280..8d3de2d 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -203,8 +203,7 @@ LayerTreeHostImpl::LayerTreeHostImpl( SharedBitmapManager* shared_bitmap_manager, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, int id) - : BeginFrameSourceMixIn(), - client_(client), + : client_(client), proxy_(proxy), use_gpu_rasterization_(false), input_handler_client_(NULL), @@ -1348,10 +1347,6 @@ void LayerTreeHostImpl::SetNeedsRedrawRect(const gfx::Rect& damage_rect) { client_->SetNeedsRedrawRectOnImplThread(damage_rect); } -void LayerTreeHostImpl::BeginFrame(const BeginFrameArgs& args) { - CallOnBeginFrame(args); -} - void LayerTreeHostImpl::DidSwapBuffers() { client_->DidSwapBuffersOnImplThread(); } @@ -1590,13 +1585,6 @@ bool LayerTreeHostImpl::SwapBuffers(const LayerTreeHostImpl::FrameData& frame) { return true; } -void LayerTreeHostImpl::OnNeedsBeginFramesChange(bool enable) { - if (output_surface_) - output_surface_->SetNeedsBeginFrame(enable); - else - DCHECK(!enable); -} - void LayerTreeHostImpl::WillBeginImplFrame(const BeginFrameArgs& args) { // Sample the frame time now. This time will be used for updating animations // when we draw. @@ -3191,10 +3179,6 @@ BeginFrameArgs LayerTreeHostImpl::CurrentBeginFrameArgs() const { BeginFrameArgs::DefaultInterval()); } -void LayerTreeHostImpl::AsValueInto(base::debug::TracedValue* value) const { - return AsValueWithFrameInto(NULL, value); -} - scoped_refptr<base::debug::ConvertableToTraceFormat> LayerTreeHostImpl::AsValue() const { return AsValueWithFrame(NULL); @@ -3208,6 +3192,10 @@ LayerTreeHostImpl::AsValueWithFrame(FrameData* frame) const { return state; } +void LayerTreeHostImpl::AsValueInto(base::debug::TracedValue* value) const { + return AsValueWithFrameInto(NULL, value); +} + void LayerTreeHostImpl::AsValueWithFrameInto( FrameData* frame, base::debug::TracedValue* state) const { diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 68d33de..df0a623 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -31,7 +31,6 @@ #include "cc/quads/render_pass.h" #include "cc/resources/resource_provider.h" #include "cc/resources/tile_manager.h" -#include "cc/scheduler/begin_frame_source.h" #include "cc/scheduler/draw_result.h" #include "skia/ext/refptr.h" #include "third_party/skia/include/core/SkColor.h" @@ -112,7 +111,6 @@ class CC_EXPORT LayerTreeHostImpl public OutputSurfaceClient, public TopControlsManagerClient, public ScrollbarAnimationControllerClient, - public BeginFrameSourceMixIn, public base::SupportsWeakPtr<LayerTreeHostImpl> { public: static scoped_ptr<LayerTreeHostImpl> Create( @@ -125,9 +123,6 @@ class CC_EXPORT LayerTreeHostImpl int id); ~LayerTreeHostImpl() override; - // BeginFrameSourceMixIn implementation - void OnNeedsBeginFramesChange(bool needs_begin_frames) override; - // InputHandler implementation void BindToClient(InputHandlerClient* client) override; InputHandler::ScrollStatus ScrollBegin( @@ -252,8 +247,6 @@ class CC_EXPORT LayerTreeHostImpl void CommitVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval) override; void SetNeedsRedrawRect(const gfx::Rect& rect) override; - void BeginFrame(const BeginFrameArgs& args) override; - void SetExternalDrawConstraints( const gfx::Transform& transform, const gfx::Rect& viewport, @@ -427,7 +420,7 @@ class CC_EXPORT LayerTreeHostImpl return begin_impl_frame_interval_; } - void AsValueInto(base::debug::TracedValue* value) const override; + void AsValueInto(base::debug::TracedValue* value) const; void AsValueWithFrameInto(FrameData* frame, base::debug::TracedValue* value) const; scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const; diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 5db3a70..e314a38 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -2116,7 +2116,8 @@ TEST(LayerTreeHostTest, PartialUpdatesWithGLRenderer) { shared_bitmap_manager.get(), NULL, settings, - base::MessageLoopProxy::current()); + base::MessageLoopProxy::current(), + nullptr); client.SetLayerTreeHost(host.get()); host->Composite(base::TimeTicks::Now()); @@ -2138,7 +2139,8 @@ TEST(LayerTreeHostTest, PartialUpdatesWithSoftwareRenderer) { shared_bitmap_manager.get(), NULL, settings, - base::MessageLoopProxy::current()); + base::MessageLoopProxy::current(), + nullptr); client.SetLayerTreeHost(host.get()); host->Composite(base::TimeTicks::Now()); @@ -2160,7 +2162,8 @@ TEST(LayerTreeHostTest, PartialUpdatesWithDelegatingRendererAndGLContent) { shared_bitmap_manager.get(), NULL, settings, - base::MessageLoopProxy::current()); + base::MessageLoopProxy::current(), + nullptr); client.SetLayerTreeHost(host.get()); host->Composite(base::TimeTicks::Now()); @@ -2183,7 +2186,8 @@ TEST(LayerTreeHostTest, shared_bitmap_manager.get(), NULL, settings, - base::MessageLoopProxy::current()); + base::MessageLoopProxy::current(), + nullptr); client.SetLayerTreeHost(host.get()); host->Composite(base::TimeTicks::Now()); diff --git a/cc/trees/layer_tree_host_unittest_no_message_loop.cc b/cc/trees/layer_tree_host_unittest_no_message_loop.cc index aa5a508..a0b2bdf 100644 --- a/cc/trees/layer_tree_host_unittest_no_message_loop.cc +++ b/cc/trees/layer_tree_host_unittest_no_message_loop.cc @@ -13,6 +13,7 @@ #include "cc/output/output_surface.h" #include "cc/output/output_surface_client.h" #include "cc/resources/resource_provider.h" +#include "cc/scheduler/begin_frame_source.h" #include "cc/test/fake_delegated_renderer_layer.h" #include "cc/test/test_context_provider.h" #include "cc/trees/layer_tree_host.h" @@ -99,7 +100,7 @@ class LayerTreeHostNoMessageLoopTest LayerTreeSettings settings; settings.single_thread_proxy_scheduler = false; layer_tree_host_ = LayerTreeHost::CreateSingleThreaded( - this, this, NULL, NULL, settings, NULL); + this, this, nullptr, nullptr, settings, nullptr, nullptr); layer_tree_host_->SetViewportSize(size_); layer_tree_host_->SetRootLayer(root_layer_); } diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc index 8e7d220..6526ff8 100644 --- a/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/cc/trees/layer_tree_host_unittest_scroll.cc @@ -8,6 +8,7 @@ #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" #include "cc/layers/picture_layer.h" +#include "cc/scheduler/begin_frame_source.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_picture_layer.h" @@ -1122,7 +1123,8 @@ TEST(LayerTreeHostFlingTest, DidStopFlingingThread) { NULL, settings, base::MessageLoopProxy::current(), - impl_thread.message_loop_proxy()); + impl_thread.message_loop_proxy(), + nullptr); impl_thread.message_loop_proxy() ->PostTask(FROM_HERE, diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index 562d7c9..f15c7ec 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc @@ -23,15 +23,20 @@ namespace cc { scoped_ptr<Proxy> SingleThreadProxy::Create( LayerTreeHost* layer_tree_host, LayerTreeHostSingleThreadClient* client, - scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) { - return make_scoped_ptr( - new SingleThreadProxy(layer_tree_host, client, main_task_runner)); + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) { + return make_scoped_ptr(new SingleThreadProxy( + layer_tree_host, + client, + main_task_runner, + external_begin_frame_source.Pass())); } SingleThreadProxy::SingleThreadProxy( LayerTreeHost* layer_tree_host, LayerTreeHostSingleThreadClient* client, - scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) : Proxy(main_task_runner, NULL), layer_tree_host_(layer_tree_host), client_(client), @@ -43,6 +48,7 @@ SingleThreadProxy::SingleThreadProxy( commit_requested_(false), inside_synchronous_composite_(false), output_surface_creation_requested_(false), + external_begin_frame_source_(external_begin_frame_source.Pass()), weak_factory_(this) { TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy"); DCHECK(Proxy::IsMainThread()); @@ -84,11 +90,13 @@ void SingleThreadProxy::SetLayerTreeHostClientReady() { if (layer_tree_host_->settings().single_thread_proxy_scheduler && !scheduler_on_impl_thread_) { SchedulerSettings scheduler_settings(layer_tree_host_->settings()); - scheduler_on_impl_thread_ = Scheduler::Create(this, - scheduler_settings, - layer_tree_host_->id(), - MainThreadTaskRunner(), - base::PowerMonitor::Get()); + scheduler_on_impl_thread_ = + Scheduler::Create(this, + scheduler_settings, + layer_tree_host_->id(), + MainThreadTaskRunner(), + base::PowerMonitor::Get(), + external_begin_frame_source_.Pass()); scheduler_on_impl_thread_->SetCanStart(); scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible()); } @@ -632,10 +640,6 @@ bool SingleThreadProxy::MainFrameWillHappenForTesting() { return false; } -BeginFrameSource* SingleThreadProxy::ExternalBeginFrameSource() { - return layer_tree_host_impl_.get(); -} - void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) { layer_tree_host_impl_->WillBeginImplFrame(args); } diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h index 5a8fee4..fa300de 100644 --- a/cc/trees/single_thread_proxy.h +++ b/cc/trees/single_thread_proxy.h @@ -19,6 +19,7 @@ namespace cc { +class BeginFrameSource; class ContextProvider; class LayerTreeHost; class LayerTreeHostSingleThreadClient; @@ -30,7 +31,8 @@ class CC_EXPORT SingleThreadProxy : public Proxy, static scoped_ptr<Proxy> Create( LayerTreeHost* layer_tree_host, LayerTreeHostSingleThreadClient* client, - scoped_refptr<base::SingleThreadTaskRunner> main_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source); ~SingleThreadProxy() override; // Proxy implementation @@ -59,7 +61,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy, bool MainFrameWillHappenForTesting() override; // SchedulerClient implementation - BeginFrameSource* ExternalBeginFrameSource() override; void WillBeginImplFrame(const BeginFrameArgs& args) override; void ScheduledActionSendBeginMainFrame() override; DrawResult ScheduledActionDrawAndSwapIfPossible() override; @@ -115,7 +116,8 @@ class CC_EXPORT SingleThreadProxy : public Proxy, SingleThreadProxy( LayerTreeHost* layer_tree_host, LayerTreeHostSingleThreadClient* client, - scoped_refptr<base::SingleThreadTaskRunner> main_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source); void BeginMainFrame(); void BeginMainFrameAbortedOnImplThread(); @@ -161,6 +163,8 @@ class CC_EXPORT SingleThreadProxy : public Proxy, // This is the callback for the scheduled RequestNewOutputSurface. base::CancelableClosure output_surface_creation_callback_; + scoped_ptr<BeginFrameSource> external_begin_frame_source_; + base::WeakPtrFactory<SingleThreadProxy> weak_factory_; DISALLOW_COPY_AND_ASSIGN(SingleThreadProxy); diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index c964d06..0f7a2a3 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc @@ -48,22 +48,27 @@ struct ThreadProxy::SchedulerStateRequest { scoped_ptr<Proxy> ThreadProxy::Create( LayerTreeHost* layer_tree_host, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) { - return make_scoped_ptr( - new ThreadProxy(layer_tree_host, main_task_runner, impl_task_runner)); + scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) { + return make_scoped_ptr(new ThreadProxy(layer_tree_host, + main_task_runner, + impl_task_runner, + external_begin_frame_source.Pass())); } ThreadProxy::ThreadProxy( LayerTreeHost* layer_tree_host, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) + scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) : Proxy(main_task_runner, impl_task_runner), main_thread_only_vars_unsafe_(this, layer_tree_host->id()), main_thread_or_blocked_vars_unsafe_(layer_tree_host), compositor_thread_vars_unsafe_( this, layer_tree_host->id(), - layer_tree_host->rendering_stats_instrumentation()) { + layer_tree_host->rendering_stats_instrumentation(), + external_begin_frame_source.Pass()) { TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy"); DCHECK(IsMainThread()); DCHECK(this->layer_tree_host()); @@ -99,7 +104,8 @@ ThreadProxy::MainThreadOrBlockedMainThread::contents_texture_manager() { ThreadProxy::CompositorThreadOnly::CompositorThreadOnly( ThreadProxy* proxy, int layer_tree_host_id, - RenderingStatsInstrumentation* rendering_stats_instrumentation) + RenderingStatsInstrumentation* rendering_stats_instrumentation, + scoped_ptr<BeginFrameSource> external_begin_frame_source) : layer_tree_host_id(layer_tree_host_id), contents_texture_manager(NULL), commit_completion_event(NULL), @@ -113,6 +119,7 @@ ThreadProxy::CompositorThreadOnly::CompositorThreadOnly( base::TimeDelta::FromMilliseconds( kSmoothnessTakesPriorityExpirationDelay * 1000)), timing_history(rendering_stats_instrumentation), + external_begin_frame_source(external_begin_frame_source.Pass()), weak_factory(proxy) { } @@ -336,10 +343,6 @@ void ThreadProxy::DidSwapBuffersCompleteOnImplThread() { base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_)); } -BeginFrameSource* ThreadProxy::ExternalBeginFrameSource() { - return impl().layer_tree_host_impl.get(); -} - void ThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) { impl().layer_tree_host_impl->WillBeginImplFrame(args); } @@ -1149,13 +1152,14 @@ void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) { impl().layer_tree_host_impl = layer_tree_host()->CreateLayerTreeHostImpl(this); SchedulerSettings scheduler_settings(layer_tree_host()->settings()); - impl().scheduler = Scheduler::Create(this, - scheduler_settings, - impl().layer_tree_host_id, - ImplThreadTaskRunner(), - base::PowerMonitor::Get()); + impl().scheduler = Scheduler::Create( + this, + scheduler_settings, + impl().layer_tree_host_id, + ImplThreadTaskRunner(), + base::PowerMonitor::Get(), + impl().external_begin_frame_source.Pass()); impl().scheduler->SetVisible(impl().layer_tree_host_impl->visible()); - impl_thread_weak_ptr_ = impl().weak_factory.GetWeakPtr(); completion->Signal(); } @@ -1213,7 +1217,6 @@ void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) { layer_tree_host()->DeleteContentsTexturesOnImplThread( impl().layer_tree_host_impl->resource_provider()); impl().current_resource_update_controller = nullptr; - impl().layer_tree_host_impl->SetNeedsBeginFrames(false); impl().scheduler = nullptr; impl().layer_tree_host_impl = nullptr; impl().weak_factory.InvalidateWeakPtrs(); diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h index 839fb3f..adccf72 100644 --- a/cc/trees/thread_proxy.h +++ b/cc/trees/thread_proxy.h @@ -25,6 +25,7 @@ class SingleThreadTaskRunner; namespace cc { +class BeginFrameSource; class ContextProvider; class InputHandlerClient; class LayerTreeHost; @@ -40,7 +41,8 @@ class CC_EXPORT ThreadProxy : public Proxy, static scoped_ptr<Proxy> Create( LayerTreeHost* layer_tree_host, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner); + scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source); ~ThreadProxy() override; @@ -96,7 +98,8 @@ class CC_EXPORT ThreadProxy : public Proxy, CompositorThreadOnly( ThreadProxy* proxy, int layer_tree_host_id, - RenderingStatsInstrumentation* rendering_stats_instrumentation); + RenderingStatsInstrumentation* rendering_stats_instrumentation, + scoped_ptr<BeginFrameSource> external_begin_frame_source); ~CompositorThreadOnly(); const int layer_tree_host_id; @@ -137,6 +140,8 @@ class CC_EXPORT ThreadProxy : public Proxy, ProxyTimingHistory timing_history; + scoped_ptr<BeginFrameSource> external_begin_frame_source; + scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl; base::WeakPtrFactory<ThreadProxy> weak_factory; }; @@ -204,7 +209,6 @@ class CC_EXPORT ThreadProxy : public Proxy, void DidManageTiles() override; // SchedulerClient implementation - BeginFrameSource* ExternalBeginFrameSource() override; void WillBeginImplFrame(const BeginFrameArgs& args) override; void ScheduledActionSendBeginMainFrame() override; DrawResult ScheduledActionDrawAndSwapIfPossible() override; @@ -225,9 +229,11 @@ class CC_EXPORT ThreadProxy : public Proxy, void ReadyToFinalizeTextureUpdates() override; protected: - ThreadProxy(LayerTreeHost* layer_tree_host, - scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner); + ThreadProxy( + LayerTreeHost* layer_tree_host, + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source); private: // Called on main thread. diff --git a/content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.cc b/content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.cc new file mode 100644 index 0000000..42dcd5b --- /dev/null +++ b/content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.cc @@ -0,0 +1,64 @@ +// Copyright 2014 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 "content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.h" + +#include "cc/output/begin_frame_args.h" +#include "content/browser/android/in_process/synchronous_compositor_impl.h" +#include "content/public/browser/browser_thread.h" + +namespace content { + +SynchronousCompositorExternalBeginFrameSource:: + SynchronousCompositorExternalBeginFrameSource(int routing_id) + : routing_id_(routing_id), + compositor_(nullptr) { +} + +SynchronousCompositorExternalBeginFrameSource:: + ~SynchronousCompositorExternalBeginFrameSource() { + DCHECK(CalledOnValidThread()); + if (compositor_) + compositor_->DidDestroyExternalBeginFrameSource(this); +} + +void SynchronousCompositorExternalBeginFrameSource::BeginFrame() { + DCHECK(CalledOnValidThread()); + CallOnBeginFrame(cc::BeginFrameArgs::CreateForSynchronousCompositor()); +} + +void SynchronousCompositorExternalBeginFrameSource::SetCompositor( + SynchronousCompositorImpl* compositor) { + DCHECK(CalledOnValidThread()); + compositor_ = compositor; +} + +void SynchronousCompositorExternalBeginFrameSource::OnNeedsBeginFramesChange( + bool needs_begin_frames) { + DCHECK(CalledOnValidThread()); + + if (compositor_) + compositor_->NeedsBeginFramesChanged(); +} + +void SynchronousCompositorExternalBeginFrameSource::SetClientReady() { + DCHECK(CalledOnValidThread()); + + SynchronousCompositorImpl* compositor = + SynchronousCompositorImpl::FromRoutingID(routing_id_); + if (compositor) { + compositor->DidInitializeExternalBeginFrameSource(this); + compositor->NeedsBeginFramesChanged(); + } +} + +// Not using base::NonThreadSafe as we want to enforce a more exacting threading +// requirement: SynchronousCompositorExternalBeginFrameSource() must only be +// used on the UI thread. +bool +SynchronousCompositorExternalBeginFrameSource::CalledOnValidThread() const { + return BrowserThread::CurrentlyOn(BrowserThread::UI); +} + +} // namespace content diff --git a/content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.h b/content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.h new file mode 100644 index 0000000..7324bf5 --- /dev/null +++ b/content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.h @@ -0,0 +1,44 @@ +// Copyright 2014 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 CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_ +#define CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "cc/scheduler/begin_frame_source.h" + +namespace content { +class SynchronousCompositorImpl; + +// Make sure that this is initialized and set to compositor before output +// surface is bound to compositor. +class SynchronousCompositorExternalBeginFrameSource + : public cc::BeginFrameSourceMixIn { + public: + explicit SynchronousCompositorExternalBeginFrameSource(int routing_id); + virtual ~SynchronousCompositorExternalBeginFrameSource(); + + void BeginFrame(); + + void SetCompositor(SynchronousCompositorImpl* compositor); + + // cc::BeginFrameSourceMixIn implementation. + void OnNeedsBeginFramesChange(bool needs_begin_frames) override; + void SetClientReady() override; + + private: + int routing_id_; + + // Not owned. This can be null when compositor is gone first than BFS. + SynchronousCompositorImpl* compositor_; + + bool CalledOnValidThread() const; + + DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorExternalBeginFrameSource); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_ diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc index 2bde4a4..4f392bf 100644 --- a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc +++ b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc @@ -5,6 +5,8 @@ #include "content/browser/android/in_process/synchronous_compositor_factory_impl.h" #include "base/observer_list.h" +#include "content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.h" +#include "content/browser/android/in_process/synchronous_compositor_impl.h" #include "content/browser/android/in_process/synchronous_compositor_output_surface.h" #include "content/public/browser/browser_thread.h" #include "content/renderer/gpu/frame_swap_message_queue.h" @@ -193,6 +195,13 @@ SynchronousCompositorFactoryImpl::GetInputHandlerManagerClient() { return synchronous_input_event_filter(); } +scoped_ptr<cc::BeginFrameSource> +SynchronousCompositorFactoryImpl::CreateExternalBeginFrameSource( + int routing_id) { + return make_scoped_ptr( + new SynchronousCompositorExternalBeginFrameSource(routing_id)); +} + scoped_refptr<ContextProviderWebContext> SynchronousCompositorFactoryImpl::CreateOffscreenContextProvider( const blink::WebGraphicsContext3D::Attributes& attributes, diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.h b/content/browser/android/in_process/synchronous_compositor_factory_impl.h index dd7467a..3f03685 100644 --- a/content/browser/android/in_process/synchronous_compositor_factory_impl.h +++ b/content/browser/android/in_process/synchronous_compositor_factory_impl.h @@ -38,6 +38,8 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory { scoped_refptr<content::FrameSwapMessageQueue> frame_swap_message_queue) override; virtual InputHandlerManagerClient* GetInputHandlerManagerClient() override; + virtual scoped_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource( + int routing_id) override; virtual scoped_refptr<webkit::gpu::ContextProviderWebContext> CreateOffscreenContextProvider( const blink::WebGraphicsContext3D::Attributes& attributes, diff --git a/content/browser/android/in_process/synchronous_compositor_impl.cc b/content/browser/android/in_process/synchronous_compositor_impl.cc index 06be5be..7fcc1a5 100644 --- a/content/browser/android/in_process/synchronous_compositor_impl.cc +++ b/content/browser/android/in_process/synchronous_compositor_impl.cc @@ -4,9 +4,11 @@ #include "content/browser/android/in_process/synchronous_compositor_impl.h" +#include "base/auto_reset.h" #include "base/lazy_instance.h" #include "base/message_loop/message_loop.h" #include "cc/input/input_handler.h" +#include "content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.h" #include "content/browser/android/in_process/synchronous_compositor_factory_impl.h" #include "content/browser/android/in_process/synchronous_input_event_filter.h" #include "content/browser/renderer_host/render_widget_host_view_android.h" @@ -65,15 +67,18 @@ SynchronousCompositorImpl* SynchronousCompositorImpl::FromRoutingID( SynchronousCompositorImpl::SynchronousCompositorImpl(WebContents* contents) : compositor_client_(NULL), output_surface_(NULL), + begin_frame_source_(nullptr), contents_(contents), input_handler_(NULL), + invoking_composite_(false), weak_ptr_factory_(this) { DCHECK(contents); } SynchronousCompositorImpl::~SynchronousCompositorImpl() { - if (compositor_client_) - compositor_client_->DidDestroyCompositor(this); + NotifyDidDestroyCompositorToClient(); + if (begin_frame_source_) + begin_frame_source_->SetCompositor(nullptr); SetInputHandler(NULL); } @@ -94,6 +99,34 @@ void SynchronousCompositor::SetRecordFullDocument(bool record_full_document) { g_factory.Get().SetRecordFullDocument(record_full_document); } +void SynchronousCompositorImpl::DidInitializeExternalBeginFrameSource( + SynchronousCompositorExternalBeginFrameSource* begin_frame_source) { + DCHECK(!begin_frame_source_); + DCHECK(!output_surface_); + DCHECK(begin_frame_source); + begin_frame_source_ = begin_frame_source; + begin_frame_source_->SetCompositor(this); +} + +void SynchronousCompositorImpl::DidDestroyExternalBeginFrameSource( + SynchronousCompositorExternalBeginFrameSource* begin_frame_source) { + DCHECK(begin_frame_source_); + DCHECK_EQ(begin_frame_source_, begin_frame_source); + begin_frame_source_->SetCompositor(nullptr); + begin_frame_source_ = nullptr; + + if (output_surface_) + output_surface_->set_external_begin_frame_source(nullptr); + + NotifyDidDestroyCompositorToClient(); +} + +void SynchronousCompositorImpl::NotifyDidDestroyCompositorToClient() { + if (compositor_client_) + compositor_client_->DidDestroyCompositor(this); + compositor_client_ = nullptr; +} + bool SynchronousCompositorImpl::InitializeHwDraw() { DCHECK(CalledOnValidThread()); DCHECK(output_surface_); @@ -124,7 +157,12 @@ scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw( const gfx::Transform& transform_for_tile_priority) { DCHECK(CalledOnValidThread()); DCHECK(output_surface_); + DCHECK(!invoking_composite_); + DCHECK(compositor_client_); + DCHECK(begin_frame_source_); + base::AutoReset<bool> invoking_composite_resetter(&invoking_composite_, + true); scoped_ptr<cc::CompositorFrame> frame = output_surface_->DemandDrawHw(surface_size, transform, @@ -135,6 +173,9 @@ scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw( if (frame.get()) UpdateFrameMetaData(frame->metadata); + compositor_client_->SetContinuousInvalidate( + begin_frame_source_->NeedsBeginFrames()); + return frame.Pass(); } @@ -147,10 +188,20 @@ void SynchronousCompositorImpl::ReturnResources( bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) { DCHECK(CalledOnValidThread()); DCHECK(output_surface_); + DCHECK(!invoking_composite_); + DCHECK(compositor_client_); + DCHECK(begin_frame_source_); - scoped_ptr<cc::CompositorFrame> frame = output_surface_->DemandDrawSw(canvas); + base::AutoReset<bool> invoking_composite_resetter(&invoking_composite_, + true); + scoped_ptr<cc::CompositorFrame> frame = + output_surface_->DemandDrawSw(canvas); if (frame.get()) UpdateFrameMetaData(frame->metadata); + + compositor_client_->SetContinuousInvalidate( + begin_frame_source_->NeedsBeginFrames()); + return !!frame.get(); } @@ -176,24 +227,27 @@ void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() { } void SynchronousCompositorImpl::DidBindOutputSurface( - SynchronousCompositorOutputSurface* output_surface) { + SynchronousCompositorOutputSurface* output_surface) { DCHECK(CalledOnValidThread()); + DCHECK(begin_frame_source_); + DCHECK(output_surface); output_surface_ = output_surface; if (compositor_client_) compositor_client_->DidInitializeCompositor(this); + + output_surface_->set_external_begin_frame_source(begin_frame_source_); } void SynchronousCompositorImpl::DidDestroySynchronousOutputSurface( - SynchronousCompositorOutputSurface* output_surface) { + SynchronousCompositorOutputSurface* output_surface) { DCHECK(CalledOnValidThread()); // Allow for transient hand-over when two output surfaces may refer to // a single delegate. if (output_surface_ == output_surface) { + output_surface_->set_external_begin_frame_source(nullptr); output_surface_ = NULL; - if (compositor_client_) - compositor_client_->DidDestroyCompositor(this); - compositor_client_ = NULL; + NotifyDidDestroyCompositorToClient(); } } @@ -226,10 +280,16 @@ void SynchronousCompositorImpl::DidStopFlinging() { rwhv->DidStopFlinging(); } -void SynchronousCompositorImpl::SetContinuousInvalidate(bool enable) { +void SynchronousCompositorImpl::NeedsBeginFramesChanged() const { DCHECK(CalledOnValidThread()); - if (compositor_client_) - compositor_client_->SetContinuousInvalidate(enable); + DCHECK(begin_frame_source_); + if (invoking_composite_) + return; + + if (compositor_client_) { + compositor_client_->SetContinuousInvalidate( + begin_frame_source_->NeedsBeginFrames()); + } } InputEventAckState SynchronousCompositorImpl::HandleInputEvent( diff --git a/content/browser/android/in_process/synchronous_compositor_impl.h b/content/browser/android/in_process/synchronous_compositor_impl.h index 9b92cef..5c24c9a 100644 --- a/content/browser/android/in_process/synchronous_compositor_impl.h +++ b/content/browser/android/in_process/synchronous_compositor_impl.h @@ -18,6 +18,7 @@ #include "ipc/ipc_message.h" namespace cc { +class BeginFrameSource; class InputHandler; } @@ -27,6 +28,7 @@ class WebInputEvent; namespace content { class InputHandlerManager; +class SynchronousCompositorExternalBeginFrameSource; struct DidOverscrollParams; // The purpose of this class is to act as the intermediary between the various @@ -48,6 +50,12 @@ class SynchronousCompositorImpl InputEventAckState HandleInputEvent(const blink::WebInputEvent& input_event); + void DidInitializeExternalBeginFrameSource( + SynchronousCompositorExternalBeginFrameSource* begin_frame_source); + void DidDestroyExternalBeginFrameSource( + SynchronousCompositorExternalBeginFrameSource* begin_frame_source); + void NeedsBeginFramesChanged() const; + // SynchronousCompositor virtual void SetClient(SynchronousCompositorClient* compositor_client) override; @@ -71,7 +79,6 @@ class SynchronousCompositorImpl SynchronousCompositorOutputSurface* output_surface) override; virtual void DidDestroySynchronousOutputSurface( SynchronousCompositorOutputSurface* output_surface) override; - virtual void SetContinuousInvalidate(bool enable) override; virtual void DidActivatePendingTree() override; // LayerScrollOffsetDelegate @@ -95,13 +102,16 @@ class SynchronousCompositorImpl friend class WebContentsUserData<SynchronousCompositorImpl>; void UpdateFrameMetaData(const cc::CompositorFrameMetadata& frame_info); + void NotifyDidDestroyCompositorToClient(); void DeliverMessages(); bool CalledOnValidThread() const; SynchronousCompositorClient* compositor_client_; SynchronousCompositorOutputSurface* output_surface_; + SynchronousCompositorExternalBeginFrameSource* begin_frame_source_; WebContents* contents_; cc::InputHandler* input_handler_; + bool invoking_composite_; base::WeakPtrFactory<SynchronousCompositorImpl> weak_ptr_factory_; diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.cc b/content/browser/android/in_process/synchronous_compositor_output_surface.cc index 1c87cc3..2438d65 100644 --- a/content/browser/android/in_process/synchronous_compositor_output_surface.cc +++ b/content/browser/android/in_process/synchronous_compositor_output_surface.cc @@ -6,11 +6,11 @@ #include "base/auto_reset.h" #include "base/logging.h" -#include "cc/output/begin_frame_args.h" #include "cc/output/compositor_frame.h" #include "cc/output/context_provider.h" #include "cc/output/output_surface_client.h" #include "cc/output/software_output_device.h" +#include "content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.h" #include "content/browser/android/in_process/synchronous_compositor_impl.h" #include "content/browser/gpu/compositor_util.h" #include "content/public/browser/browser_thread.h" @@ -76,8 +76,6 @@ SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface( : cc::OutputSurface( scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareDevice(this))), routing_id_(routing_id), - needs_begin_frame_(false), - invoking_composite_(false), current_sw_canvas_(NULL), memory_policy_(0), output_surface_client_(NULL), @@ -124,14 +122,6 @@ void SynchronousCompositorOutputSurface::Reshape( // Intentional no-op: surface size is controlled by the embedder. } -void SynchronousCompositorOutputSurface::SetNeedsBeginFrame(bool enable) { - DCHECK(CalledOnValidThread()); - needs_begin_frame_ = enable; - SynchronousCompositorOutputSurfaceDelegate* delegate = GetDelegate(); - if (delegate && !invoking_composite_) - delegate->SetContinuousInvalidate(needs_begin_frame_); -} - void SynchronousCompositorOutputSurface::SwapBuffers( cc::CompositorFrame* frame) { DCHECK(CalledOnValidThread()); @@ -223,9 +213,8 @@ void SynchronousCompositorOutputSurface::InvokeComposite( gfx::Rect viewport_rect_for_tile_priority, gfx::Transform transform_for_tile_priority, bool hardware_draw) { - DCHECK(!invoking_composite_); DCHECK(!frame_holder_.get()); - base::AutoReset<bool> invoking_composite_resetter(&invoking_composite_, true); + DCHECK(begin_frame_source_); gfx::Transform adjusted_transform = transform; AdjustTransform(&adjusted_transform, viewport); @@ -236,7 +225,8 @@ void SynchronousCompositorOutputSurface::InvokeComposite( transform_for_tile_priority, !hardware_draw); SetNeedsRedrawRect(gfx::Rect(viewport.size())); - client_->BeginFrame(cc::BeginFrameArgs::CreateForSynchronousCompositor()); + + begin_frame_source_->BeginFrame(); // After software draws (which might move the viewport arbitrarily), restore // the previous hardware viewport to allow CC's tile manager to prioritize @@ -260,10 +250,6 @@ void SynchronousCompositorOutputSurface::InvokeComposite( if (frame_holder_.get()) client_->DidSwapBuffersComplete(); - - SynchronousCompositorOutputSurfaceDelegate* delegate = GetDelegate(); - if (delegate) - delegate->SetContinuousInvalidate(needs_begin_frame_); } void SynchronousCompositorOutputSurface::ReturnResources( diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.h b/content/browser/android/in_process/synchronous_compositor_output_surface.h index d01d88b..a9bb4fc 100644 --- a/content/browser/android/in_process/synchronous_compositor_output_surface.h +++ b/content/browser/android/in_process/synchronous_compositor_output_surface.h @@ -31,6 +31,7 @@ namespace content { class FrameSwapMessageQueue; class SynchronousCompositorClient; +class SynchronousCompositorExternalBeginFrameSource; class SynchronousCompositorOutputSurface; class WebGraphicsContext3DCommandBufferImpl; @@ -40,7 +41,6 @@ class SynchronousCompositorOutputSurfaceDelegate { SynchronousCompositorOutputSurface* output_surface) = 0; virtual void DidDestroySynchronousOutputSurface( SynchronousCompositorOutputSurface* output_surface) = 0; - virtual void SetContinuousInvalidate(bool enable) = 0; virtual void DidActivatePendingTree() = 0; protected: @@ -67,7 +67,6 @@ class SynchronousCompositorOutputSurface // OutputSurface. virtual bool BindToClient(cc::OutputSurfaceClient* surface_client) override; virtual void Reshape(const gfx::Size& size, float scale_factor) override; - virtual void SetNeedsBeginFrame(bool enable) override; virtual void SwapBuffers(cc::CompositorFrame* frame) override; // Partial SynchronousCompositor API implementation. @@ -86,6 +85,11 @@ class SynchronousCompositorOutputSurface void SetMemoryPolicy(size_t bytes_limit); void GetMessagesToDeliver(ScopedVector<IPC::Message>* messages); + void set_external_begin_frame_source( + SynchronousCompositorExternalBeginFrameSource* begin_frame_source) { + begin_frame_source_ = begin_frame_source; + } + private: class SoftwareDevice; friend class SoftwareDevice; @@ -100,8 +104,6 @@ class SynchronousCompositorOutputSurface SynchronousCompositorOutputSurfaceDelegate* GetDelegate(); int routing_id_; - bool needs_begin_frame_; - bool invoking_composite_; gfx::Transform cached_hw_transform_; gfx::Rect cached_hw_viewport_; @@ -119,6 +121,8 @@ class SynchronousCompositorOutputSurface scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_; + SynchronousCompositorExternalBeginFrameSource* begin_frame_source_; + DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorOutputSurface); }; diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 05eae79..9493928 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc @@ -27,6 +27,7 @@ #include "cc/output/context_provider.h" #include "cc/output/output_surface.h" #include "cc/output/output_surface_client.h" +#include "cc/scheduler/begin_frame_source.h" #include "cc/trees/layer_tree_host.h" #include "content/browser/android/child_process_launcher_android.h" #include "content/browser/gpu/browser_gpu_channel_host_factory.h" @@ -409,7 +410,8 @@ void CompositorImpl::SetVisible(bool visible) { HostSharedBitmapManager::current(), BrowserGpuMemoryBufferManager::current(), settings, - base::MessageLoopProxy::current()); + base::MessageLoopProxy::current(), + nullptr); host_->SetRootLayer(root_layer_); host_->SetVisible(true); diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 3a2dc88..f048828 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc @@ -308,8 +308,8 @@ bool RenderWidgetHostViewAndroid::OnMessageReceived( IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent) IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor, OnDidChangeBodyBackgroundColor) - IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame, - OnSetNeedsBeginFrame) + IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames, + OnSetNeedsBeginFrames) IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged, OnTextInputStateChanged) IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted, @@ -673,9 +673,9 @@ void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor( content_view_core_->OnBackgroundColorChanged(color); } -void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) { +void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrames(bool enabled) { DCHECK(!using_synchronous_compositor_); - TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame", + TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrames", "enabled", enabled); if (enabled) RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME); diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index 063a515..cff7cc1 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h @@ -223,7 +223,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid void OnTextInputStateChanged(const ViewHostMsg_TextInputState_Params& params); void OnDidChangeBodyBackgroundColor(SkColor color); void OnStartContentIntent(const GURL& content_url); - void OnSetNeedsBeginFrame(bool enabled); + void OnSetNeedsBeginFrames(bool enabled); void OnSmartClipDataExtracted(const base::string16& text, const base::string16& html, const gfx::Rect rect); diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 426ac1f..6ce4333 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -905,10 +905,6 @@ IPC_MESSAGE_ROUTED3(ViewMsg_UpdateTopControlsState, IPC_MESSAGE_ROUTED0(ViewMsg_ShowImeIfNeeded) -// Sent by the browser when the renderer should generate a new frame. -IPC_MESSAGE_ROUTED1(ViewMsg_BeginFrame, - cc::BeginFrameArgs /* args */) - // Sent by the browser when an IME update that requires acknowledgement has been // processed on the browser side. IPC_MESSAGE_ROUTED0(ViewMsg_ImeEventAck) @@ -958,9 +954,19 @@ IPC_MESSAGE_ROUTED0(ViewMsg_SelectWordAroundCaret) IPC_MESSAGE_ROUTED1(ViewMsg_ForceRedraw, int /* request_id */) +// Sent by the browser when the renderer should generate a new frame. +IPC_MESSAGE_ROUTED1(ViewMsg_BeginFrame, + cc::BeginFrameArgs /* args */) + // ----------------------------------------------------------------------------- // Messages sent from the renderer to the browser. +// Sent by renderer to request a ViewMsg_BeginFrame message for upcoming +// display events. If |enabled| is true, the BeginFrame message will continue +// to be be delivered until the notification is disabled. +IPC_MESSAGE_ROUTED1(ViewHostMsg_SetNeedsBeginFrames, + bool /* enabled */) + // Sent by the renderer when it is creating a new window. The browser creates // a tab for it and responds with a ViewMsg_CreatingNew_ACK. If route_id is // MSG_ROUTING_NONE, the view couldn't be created. @@ -1587,12 +1593,6 @@ IPC_MESSAGE_CONTROL3(ViewHostMsg_RunWebAudioMediaCodec, base::FileDescriptor /* pcm_output */, uint32_t /* data_size*/) -// Sent by renderer to request a ViewMsg_BeginFrame message for upcoming -// display events. If |enabled| is true, the BeginFrame message will continue -// to be be delivered until the notification is disabled. -IPC_MESSAGE_ROUTED1(ViewHostMsg_SetNeedsBeginFrame, - bool /* enabled */) - // Reply to the ViewMsg_ExtractSmartClipData message. IPC_MESSAGE_ROUTED3(ViewHostMsg_SmartClipDataExtracted, base::string16 /* text */, diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 5645a74..f22759c 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -308,6 +308,8 @@ 'browser/android/edge_effect_l.cc', 'browser/android/edge_effect_l.h', 'browser/android/gesture_event_type_list.h', + 'browser/android/in_process/synchronous_compositor_external_begin_frame_source.cc', + 'browser/android/in_process/synchronous_compositor_external_begin_frame_source.h', 'browser/android/in_process/synchronous_compositor_factory_impl.cc', 'browser/android/in_process/synchronous_compositor_factory_impl.h', 'browser/android/in_process/synchronous_compositor_impl.cc', diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 2166543..8731bb0 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -158,6 +158,10 @@ 'renderer/gamepad_shared_memory_reader.h', 'renderer/geolocation_dispatcher.cc', 'renderer/geolocation_dispatcher.h', + 'renderer/gpu/compositor_external_begin_frame_source.cc', + 'renderer/gpu/compositor_external_begin_frame_source.h', + 'renderer/gpu/compositor_forwarding_message_filter.cc', + 'renderer/gpu/compositor_forwarding_message_filter.h', 'renderer/gpu/compositor_output_surface.cc', 'renderer/gpu/compositor_output_surface.h', 'renderer/gpu/compositor_software_output_device.cc', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 16f3124..98e75ae 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -703,6 +703,7 @@ 'renderer/device_sensors/device_orientation_event_pump_unittest.cc', 'renderer/disambiguation_popup_helper_unittest.cc', 'renderer/dom_storage/dom_storage_cached_area_unittest.cc', + 'renderer/gpu/compositor_forwarding_message_filter_unittest.cc', 'renderer/gpu/frame_swap_message_queue_unittest.cc', 'renderer/gpu/queue_message_swap_promise_unittest.cc', 'renderer/gpu/render_widget_compositor_unittest.cc', diff --git a/content/renderer/android/synchronous_compositor_factory.h b/content/renderer/android/synchronous_compositor_factory.h index 9653bc2..6eb6430 100644 --- a/content/renderer/android/synchronous_compositor_factory.h +++ b/content/renderer/android/synchronous_compositor_factory.h @@ -14,6 +14,7 @@ class MessageLoopProxy; } namespace cc { +class BeginFrameSource; class ContextProvider; class OutputSurface; } @@ -52,6 +53,9 @@ class SynchronousCompositorFactory { // The factory maintains ownership of the returned interface. virtual InputHandlerManagerClient* GetInputHandlerManagerClient() = 0; + virtual scoped_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource( + int routing_id) = 0; + virtual scoped_refptr<webkit::gpu::ContextProviderWebContext> CreateOffscreenContextProvider( const blink::WebGraphicsContext3D::Attributes& attributes, diff --git a/content/renderer/gpu/compositor_external_begin_frame_source.cc b/content/renderer/gpu/compositor_external_begin_frame_source.cc new file mode 100644 index 0000000..4fa9312 --- /dev/null +++ b/content/renderer/gpu/compositor_external_begin_frame_source.cc @@ -0,0 +1,73 @@ +// Copyright 2014 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 "content/renderer/gpu/compositor_external_begin_frame_source.h" + +#include "content/common/view_messages.h" +#include "content/renderer/render_thread_impl.h" +#include "ipc/ipc_sync_channel.h" +#include "ipc/ipc_sync_message_filter.h" + +namespace content { + +CompositorExternalBeginFrameSource::CompositorExternalBeginFrameSource( + int routing_id) + : begin_frame_source_filter_( + RenderThreadImpl::current()->compositor_message_filter()), + message_sender_(RenderThreadImpl::current()->sync_message_filter()), + routing_id_(routing_id) { + DCHECK(begin_frame_source_filter_.get()); + DCHECK(message_sender_.get()); + DetachFromThread(); +} + +CompositorExternalBeginFrameSource::~CompositorExternalBeginFrameSource() { + DCHECK(CalledOnValidThread()); + if (begin_frame_source_proxy_.get()) { + begin_frame_source_proxy_->ClearBeginFrameSource(); + begin_frame_source_filter_->RemoveHandlerOnCompositorThread( + routing_id_, + begin_frame_source_filter_handler_); + } +} + +void CompositorExternalBeginFrameSource::OnNeedsBeginFramesChange( + bool needs_begin_frames) { + DCHECK(CalledOnValidThread()); + Send(new ViewHostMsg_SetNeedsBeginFrames(routing_id_, needs_begin_frames)); +} + +void CompositorExternalBeginFrameSource::SetClientReady() { + DCHECK(CalledOnValidThread()); + DCHECK(!begin_frame_source_proxy_.get()); + begin_frame_source_proxy_ = + new CompositorExternalBeginFrameSourceProxy(this); + begin_frame_source_filter_handler_ = base::Bind( + &CompositorExternalBeginFrameSourceProxy::OnMessageReceived, + begin_frame_source_proxy_); + begin_frame_source_filter_->AddHandlerOnCompositorThread( + routing_id_, + begin_frame_source_filter_handler_); +} + +void CompositorExternalBeginFrameSource::OnMessageReceived( + const IPC::Message& message) { + DCHECK(CalledOnValidThread()); + DCHECK(begin_frame_source_proxy_.get()); + IPC_BEGIN_MESSAGE_MAP(CompositorExternalBeginFrameSource, message) + IPC_MESSAGE_HANDLER(ViewMsg_BeginFrame, OnBeginFrame) + IPC_END_MESSAGE_MAP(); +} + +void CompositorExternalBeginFrameSource::OnBeginFrame( + const cc::BeginFrameArgs& args) { + DCHECK(CalledOnValidThread()); + CallOnBeginFrame(args); +} + +bool CompositorExternalBeginFrameSource::Send(IPC::Message* message) { + return message_sender_->Send(message); +} + +} // namespace content diff --git a/content/renderer/gpu/compositor_external_begin_frame_source.h b/content/renderer/gpu/compositor_external_begin_frame_source.h new file mode 100644 index 0000000..ba78693 --- /dev/null +++ b/content/renderer/gpu/compositor_external_begin_frame_source.h @@ -0,0 +1,75 @@ +// Copyright 2014 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 CONTENT_RENDERER_GPU_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_H_ +#define CONTENT_RENDERER_GPU_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" +#include "cc/scheduler/begin_frame_source.h" +#include "content/renderer/gpu/compositor_forwarding_message_filter.h" + +namespace IPC { +class Message; +class SyncMessageFilter; +} + +namespace content { + +// This class can be created only on the main thread, but then becomes pinned +// to a fixed thread where cc::Scheduler is running. +class CompositorExternalBeginFrameSource + : public cc::BeginFrameSourceMixIn, + public NON_EXPORTED_BASE(base::NonThreadSafe) { + public: + explicit CompositorExternalBeginFrameSource(int routing_id); + virtual ~CompositorExternalBeginFrameSource(); + + // cc::BeginFrameSourceMixIn implementation. + virtual void OnNeedsBeginFramesChange(bool needs_begin_frames) override; + virtual void SetClientReady() override; + + private: + class CompositorExternalBeginFrameSourceProxy + : public base::RefCountedThreadSafe< + CompositorExternalBeginFrameSourceProxy> { + public: + explicit CompositorExternalBeginFrameSourceProxy( + CompositorExternalBeginFrameSource* begin_frame_source) + : begin_frame_source_(begin_frame_source) {} + void ClearBeginFrameSource() { begin_frame_source_ = NULL; } + void OnMessageReceived(const IPC::Message& message) { + if (begin_frame_source_) + begin_frame_source_->OnMessageReceived(message); + } + + private: + friend class base::RefCountedThreadSafe< + CompositorExternalBeginFrameSourceProxy>; + virtual ~CompositorExternalBeginFrameSourceProxy() {} + + CompositorExternalBeginFrameSource* begin_frame_source_; + + DISALLOW_COPY_AND_ASSIGN(CompositorExternalBeginFrameSourceProxy); + }; + + void OnMessageReceived(const IPC::Message& message); + + void OnBeginFrame(const cc::BeginFrameArgs& args); + bool Send(IPC::Message* message); + + scoped_refptr<CompositorForwardingMessageFilter> begin_frame_source_filter_; + scoped_refptr<CompositorExternalBeginFrameSourceProxy> + begin_frame_source_proxy_; + scoped_refptr<IPC::SyncMessageFilter> message_sender_; + int routing_id_; + CompositorForwardingMessageFilter::Handler begin_frame_source_filter_handler_; + + DISALLOW_COPY_AND_ASSIGN(CompositorExternalBeginFrameSource); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_GPU_COMPOSITOR_EXTERNAL_BEGIN_FRAME_SOURCE_H_ diff --git a/content/renderer/gpu/compositor_forwarding_message_filter.cc b/content/renderer/gpu/compositor_forwarding_message_filter.cc new file mode 100644 index 0000000..ff657dc --- /dev/null +++ b/content/renderer/gpu/compositor_forwarding_message_filter.cc @@ -0,0 +1,79 @@ +// Copyright 2014 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 "content/renderer/gpu//compositor_forwarding_message_filter.h" + +#include "base/bind.h" +#include "base/location.h" +#include "content/common/view_messages.h" +#include "ipc/ipc_message.h" + +namespace content { + +CompositorForwardingMessageFilter::CompositorForwardingMessageFilter( + base::TaskRunner* compositor_task_runner) + : compositor_task_runner_(compositor_task_runner) { + DCHECK(compositor_task_runner_.get()); + // This check will only be used by functions running on compositor thread. + compositor_thread_checker_.DetachFromThread(); +} + +CompositorForwardingMessageFilter::~CompositorForwardingMessageFilter() { +} + +void CompositorForwardingMessageFilter::AddHandlerOnCompositorThread( + int routing_id, + const Handler& handler) { + DCHECK(compositor_thread_checker_.CalledOnValidThread()); + DCHECK(!handler.is_null()); + multi_handlers_.insert(std::make_pair(routing_id, handler)); +} + +void CompositorForwardingMessageFilter::RemoveHandlerOnCompositorThread( + int routing_id, + const Handler& handler) { + DCHECK(compositor_thread_checker_.CalledOnValidThread()); + auto handlers = multi_handlers_.equal_range(routing_id); + for (auto it = handlers.first; it != handlers.second; ++it) { + if (it->second.Equals(handler)) { + multi_handlers_.erase(it); + return; + } + } + NOTREACHED(); +} + +bool CompositorForwardingMessageFilter::OnMessageReceived( + const IPC::Message& message) { + switch(message.type()) { + case ViewMsg_BeginFrame::ID: // Fall through. + case ViewMsg_ReclaimCompositorResources::ID: // Fall through. + case ViewMsg_SwapCompositorFrameAck::ID: // Fall through. + case ViewMsg_UpdateVSyncParameters::ID: + break; + default: + return false; + } + + compositor_task_runner_->PostTask( + FROM_HERE, + base::Bind( + &CompositorForwardingMessageFilter::ProcessMessageOnCompositorThread, + this, + message)); + return true; +} + +void CompositorForwardingMessageFilter::ProcessMessageOnCompositorThread( + const IPC::Message& message) { + DCHECK(compositor_thread_checker_.CalledOnValidThread()); + auto handlers = multi_handlers_.equal_range(message.routing_id()); + if (handlers.first == handlers.second) + return; + + for (auto it = handlers.first; it != handlers.second; ++it) + it->second.Run(message); +} + +} // namespace content diff --git a/content/renderer/gpu/compositor_forwarding_message_filter.h b/content/renderer/gpu/compositor_forwarding_message_filter.h new file mode 100644 index 0000000..7f9c720 --- /dev/null +++ b/content/renderer/gpu/compositor_forwarding_message_filter.h @@ -0,0 +1,74 @@ +// Copyright 2014 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 CONTENT_RENDERER_GPU_COMPOSITOR_FORWARDING_MESSAGE_FILTER_H_ +#define CONTENT_RENDERER_GPU_COMPOSITOR_FORWARDING_MESSAGE_FILTER_H_ + +#include <map> +#include <set> + +#include "base/bind.h" +#include "base/callback_forward.h" +#include "base/synchronization/lock.h" +#include "base/task_runner.h" +#include "base/threading/thread_checker.h" +#include "content/common/content_export.h" +#include "ipc/message_filter.h" + +namespace content { + +// This class can be used to intercept routed messages and +// deliver them to a compositor task runner than they would otherwise +// be sent. Messages are filtered based on type. To route these messages, +// add a Handler to the filter. +// +// The user of this class implements CompositorForwardingMessageFilter::Handler, +// which will receive the intercepted messages, on the compositor thread. +// The caller must ensure that each handler in |multi_handlers_| outlives the +// lifetime of the filter. +// User can add multiple handlers for specific routing id. When messages have +// arrived, all handlers in |multi_handlers_| for routing id will be executed. +// +// Note: When we want to add new message, add a new switch case in +// OnMessageReceived() then add a new Handler for it. +class CONTENT_EXPORT CompositorForwardingMessageFilter + : public IPC::MessageFilter { + public: + // The handler is invoked on the compositor thread with messages that were + // intercepted by this filter. + typedef base::Callback<void(const IPC::Message&)> Handler; + + // This filter will intercept messages defined in OnMessageReceived() and run + // them by ProcessMessageOnCompositorThread on compositor thread. + CompositorForwardingMessageFilter(base::TaskRunner* compositor_task_runner); + + void AddHandlerOnCompositorThread(int routing_id, const Handler& handler); + void RemoveHandlerOnCompositorThread(int routing_id, const Handler& handler); + + // MessageFilter methods: + virtual bool OnMessageReceived(const IPC::Message& message) override; + + protected: + virtual ~CompositorForwardingMessageFilter(); + + private: + void ProcessMessageOnCompositorThread(const IPC::Message& message); + + // The handler only gets run on the compositor thread. + scoped_refptr<base::TaskRunner> compositor_task_runner_; + + // This is used to check some functions that are only running on compositor + // thread. + base::ThreadChecker compositor_thread_checker_; + + // Maps the routing_id for which messages should be filtered and handlers + // which will be routed. + std::multimap<int, Handler> multi_handlers_; + + DISALLOW_COPY_AND_ASSIGN(CompositorForwardingMessageFilter); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_GPU_COMPOSITOR_FORWARDING_MESSAGE_FILTER_H_ diff --git a/content/renderer/gpu/compositor_forwarding_message_filter_unittest.cc b/content/renderer/gpu/compositor_forwarding_message_filter_unittest.cc new file mode 100644 index 0000000..6a21a84 --- /dev/null +++ b/content/renderer/gpu/compositor_forwarding_message_filter_unittest.cc @@ -0,0 +1,81 @@ +// Copyright 2014 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 "content/renderer/gpu/compositor_forwarding_message_filter.h" + +#include "base/bind.h" +#include "base/test/test_simple_task_runner.h" +#include "cc/test/begin_frame_args_test.h" +#include "content/common/view_messages.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +class CompositorForwardingMessageFilterTestHandler + : public base::RefCounted<CompositorForwardingMessageFilterTestHandler> { + public: + CompositorForwardingMessageFilterTestHandler() : count_(0) { + } + + void OnPlusMethod(const IPC::Message& msg) { + count_++; + } + + void OnMinusMethod(const IPC::Message& msg) { + count_--; + } + + int count() { return count_; } + + void ResetCount() { count_ = 0; } + + private: + friend class base::RefCounted<CompositorForwardingMessageFilterTestHandler>; + ~CompositorForwardingMessageFilterTestHandler() {} + + int count_; +}; + +TEST(CompositorForwardingMessageFilterTest, BasicTest) { + scoped_refptr<CompositorForwardingMessageFilterTestHandler> handler = + new CompositorForwardingMessageFilterTestHandler; + scoped_refptr<base::TestSimpleTaskRunner> task_runner( + new base::TestSimpleTaskRunner); + int route_id = 0; + + ViewMsg_BeginFrame msg(route_id, cc::CreateBeginFrameArgsForTesting()); + + CompositorForwardingMessageFilter::Handler plus_handler = + base::Bind(&CompositorForwardingMessageFilterTestHandler::OnPlusMethod, + handler); + CompositorForwardingMessageFilter::Handler minus_handler = + base::Bind(&CompositorForwardingMessageFilterTestHandler::OnMinusMethod, + handler); + + scoped_refptr<CompositorForwardingMessageFilter> filter = + new CompositorForwardingMessageFilter(task_runner.get()); + + filter->AddHandlerOnCompositorThread(route_id, plus_handler); + filter->OnMessageReceived(msg); + task_runner->RunPendingTasks(); + EXPECT_EQ(1, handler->count()); + + handler->ResetCount(); + EXPECT_EQ(0, handler->count()); + + filter->AddHandlerOnCompositorThread(route_id, minus_handler); + filter->OnMessageReceived(msg); + task_runner->RunPendingTasks(); + EXPECT_EQ(0, handler->count()); + + handler->ResetCount(); + EXPECT_EQ(0, handler->count()); + + filter->RemoveHandlerOnCompositorThread(route_id, plus_handler); + filter->OnMessageReceived(msg); + task_runner->RunPendingTasks(); + EXPECT_EQ(-1, handler->count()); +} + +} // namespace content diff --git a/content/renderer/gpu/compositor_output_surface.cc b/content/renderer/gpu/compositor_output_surface.cc index c579d8c..4e2874c 100644 --- a/content/renderer/gpu/compositor_output_surface.cc +++ b/content/renderer/gpu/compositor_output_surface.cc @@ -19,7 +19,6 @@ #include "content/renderer/render_thread_impl.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" -#include "ipc/ipc_forwarding_message_filter.h" #include "ipc/ipc_sync_channel.h" namespace { @@ -30,26 +29,6 @@ int g_prefer_smoothness_count = 0; namespace content { -//------------------------------------------------------------------------------ - -// static -IPC::ForwardingMessageFilter* CompositorOutputSurface::CreateFilter( - base::TaskRunner* target_task_runner) -{ - uint32 messages_to_filter[] = { - ViewMsg_UpdateVSyncParameters::ID, - ViewMsg_SwapCompositorFrameAck::ID, - ViewMsg_ReclaimCompositorResources::ID, -#if defined(OS_ANDROID) - ViewMsg_BeginFrame::ID -#endif - }; - - return new IPC::ForwardingMessageFilter( - messages_to_filter, arraysize(messages_to_filter), - target_task_runner); -} - CompositorOutputSurface::CompositorOutputSurface( int32 routing_id, uint32 output_surface_id, @@ -61,7 +40,7 @@ CompositorOutputSurface::CompositorOutputSurface( output_surface_id_(output_surface_id), use_swap_compositor_frame_message_(use_swap_compositor_frame_message), output_surface_filter_( - RenderThreadImpl::current()->compositor_output_surface_filter()), + RenderThreadImpl::current()->compositor_message_filter()), frame_swap_message_queue_(swap_frame_message_queue), routing_id_(routing_id), prefers_smoothness_(false), @@ -84,13 +63,14 @@ CompositorOutputSurface::CompositorOutputSurface( CompositorOutputSurface::~CompositorOutputSurface() { DCHECK(CalledOnValidThread()); - SetNeedsBeginFrame(false); if (!HasClient()) return; UpdateSmoothnessTakesPriority(false); if (output_surface_proxy_.get()) output_surface_proxy_->ClearOutputSurface(); - output_surface_filter_->RemoveRoute(routing_id_); + output_surface_filter_->RemoveHandlerOnCompositorThread( + routing_id_, + output_surface_filter_handler_); } bool CompositorOutputSurface::BindToClient( @@ -101,10 +81,12 @@ bool CompositorOutputSurface::BindToClient( return false; output_surface_proxy_ = new CompositorOutputSurfaceProxy(this); - output_surface_filter_->AddRoute( - routing_id_, + output_surface_filter_handler_ = base::Bind(&CompositorOutputSurfaceProxy::OnMessageReceived, - output_surface_proxy_)); + output_surface_proxy_); + output_surface_filter_->AddHandlerOnCompositorThread( + routing_id_, + output_surface_filter_handler_); if (!context_provider()) { // Without a GPU context, the memory policy otherwise wouldn't be set. @@ -193,9 +175,6 @@ void CompositorOutputSurface::OnMessageReceived(const IPC::Message& message) { OnUpdateVSyncParametersFromBrowser); IPC_MESSAGE_HANDLER(ViewMsg_SwapCompositorFrameAck, OnSwapAck); IPC_MESSAGE_HANDLER(ViewMsg_ReclaimCompositorResources, OnReclaimResources); -#if defined(OS_ANDROID) - IPC_MESSAGE_HANDLER(ViewMsg_BeginFrame, OnBeginFrame); -#endif IPC_END_MESSAGE_MAP() } @@ -206,18 +185,6 @@ void CompositorOutputSurface::OnUpdateVSyncParametersFromBrowser( CommitVSyncParameters(timebase, interval); } -#if defined(OS_ANDROID) -void CompositorOutputSurface::SetNeedsBeginFrame(bool enable) { - DCHECK(CalledOnValidThread()); - Send(new ViewHostMsg_SetNeedsBeginFrame(routing_id_, enable)); -} - -void CompositorOutputSurface::OnBeginFrame(const cc::BeginFrameArgs& args) { - DCHECK(CalledOnValidThread()); - client_->BeginFrame(args); -} -#endif // defined(OS_ANDROID) - void CompositorOutputSurface::OnSwapAck(uint32 output_surface_id, const cc::CompositorFrameAck& ack) { // Ignore message if it's a stale one coming from a different output surface diff --git a/content/renderer/gpu/compositor_output_surface.h b/content/renderer/gpu/compositor_output_surface.h index 7ee9427..a8e1764 100644 --- a/content/renderer/gpu/compositor_output_surface.h +++ b/content/renderer/gpu/compositor_output_surface.h @@ -15,14 +15,10 @@ #include "base/time/time.h" #include "cc/output/begin_frame_args.h" #include "cc/output/output_surface.h" +#include "content/renderer/gpu/compositor_forwarding_message_filter.h" #include "ipc/ipc_sync_message_filter.h" -namespace base { -class TaskRunner; -} - namespace IPC { -class ForwardingMessageFilter; class Message; } @@ -43,9 +39,6 @@ class CompositorOutputSurface : NON_EXPORTED_BASE(public cc::OutputSurface), NON_EXPORTED_BASE(public base::NonThreadSafe) { public: - static IPC::ForwardingMessageFilter* CreateFilter( - base::TaskRunner* target_task_runner); - CompositorOutputSurface( int32 routing_id, uint32 output_surface_id, @@ -58,9 +51,6 @@ class CompositorOutputSurface // cc::OutputSurface implementation. bool BindToClient(cc::OutputSurfaceClient* client) override; void SwapBuffers(cc::CompositorFrame* frame) override; -#if defined(OS_ANDROID) - virtual void SetNeedsBeginFrame(bool enable) override; -#endif // TODO(epenner): This seems out of place here and would be a better fit // int CompositorThread after it is fully refactored (http://crbug/170828) @@ -100,14 +90,12 @@ class CompositorOutputSurface void OnMessageReceived(const IPC::Message& message); void OnUpdateVSyncParametersFromBrowser(base::TimeTicks timebase, base::TimeDelta interval); -#if defined(OS_ANDROID) - void OnBeginFrame(const cc::BeginFrameArgs& args); -#endif bool Send(IPC::Message* message); bool use_swap_compositor_frame_message_; - scoped_refptr<IPC::ForwardingMessageFilter> output_surface_filter_; + scoped_refptr<CompositorForwardingMessageFilter> output_surface_filter_; + CompositorForwardingMessageFilter::Handler output_surface_filter_handler_; scoped_refptr<CompositorOutputSurfaceProxy> output_surface_proxy_; scoped_refptr<IPC::SyncMessageFilter> message_sender_; scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_; diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index 3e12f2e..491dc13 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc @@ -33,6 +33,7 @@ #include "content/common/content_switches_internal.h" #include "content/common/gpu/client/context_provider_command_buffer.h" #include "content/public/common/content_switches.h" +#include "content/renderer/gpu/compositor_external_begin_frame_source.h" #include "content/renderer/input/input_handler_manager.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/scheduler/renderer_scheduler.h" @@ -535,6 +536,21 @@ void RenderWidgetCompositor::Initialize(cc::LayerTreeSettings settings) { main_thread_compositor_task_runner = render_thread->main_thread_compositor_task_runner(); } + scoped_ptr<cc::BeginFrameSource> external_begin_frame_source; +#if defined(OS_ANDROID) + if (SynchronousCompositorFactory* factory = + SynchronousCompositorFactory::GetInstance()) { + DCHECK(settings.begin_frame_scheduling_enabled); + external_begin_frame_source = + factory->CreateExternalBeginFrameSource(widget_->routing_id()); + } +#endif + if (render_thread && + !external_begin_frame_source.get() && + settings.begin_frame_scheduling_enabled) { + external_begin_frame_source.reset(new CompositorExternalBeginFrameSource( + widget_->routing_id())); + } if (compositor_message_loop_proxy.get()) { layer_tree_host_ = cc::LayerTreeHost::CreateThreaded(this, @@ -542,15 +558,17 @@ void RenderWidgetCompositor::Initialize(cc::LayerTreeSettings settings) { gpu_memory_buffer_manager, settings, main_thread_compositor_task_runner, - compositor_message_loop_proxy); + compositor_message_loop_proxy, + external_begin_frame_source.Pass()); } else { layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded( - this, - this, - shared_bitmap_manager, - gpu_memory_buffer_manager, - settings, - main_thread_compositor_task_runner); + this, + this, + shared_bitmap_manager, + gpu_memory_buffer_manager, + settings, + main_thread_compositor_task_runner, + external_begin_frame_source.Pass()); } DCHECK(layer_tree_host_); } diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index c51a2a8..ebc30cd 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -75,6 +75,8 @@ #include "content/renderer/dom_storage/dom_storage_dispatcher.h" #include "content/renderer/dom_storage/webstoragearea_impl.h" #include "content/renderer/dom_storage/webstoragenamespace_impl.h" +#include "content/renderer/gpu/compositor_external_begin_frame_source.h" +#include "content/renderer/gpu/compositor_forwarding_message_filter.h" #include "content/renderer/gpu/compositor_output_surface.h" #include "content/renderer/input/input_event_filter.h" #include "content/renderer/input/input_handler_manager.h" @@ -98,7 +100,6 @@ #include "content/renderer/service_worker/embedded_worker_dispatcher.h" #include "content/renderer/shared_worker/embedded_shared_worker_stub.h" #include "ipc/ipc_channel_handle.h" -#include "ipc/ipc_forwarding_message_filter.h" #include "ipc/ipc_platform_file.h" #include "ipc/mojo/ipc_channel_mojo.h" #include "media/base/audio_hardware_config.h" @@ -643,9 +644,9 @@ void RenderThreadImpl::Shutdown() { if (file_thread_) file_thread_->Stop(); - if (compositor_output_surface_filter_.get()) { - RemoveFilter(compositor_output_surface_filter_.get()); - compositor_output_surface_filter_ = NULL; + if (compositor_message_filter_.get()) { + RemoveFilter(compositor_message_filter_.get()); + compositor_message_filter_ = NULL; } media_thread_.reset(); @@ -918,15 +919,15 @@ void RenderThreadImpl::EnsureWebKitInitialized() { renderer_scheduler())); } - scoped_refptr<base::MessageLoopProxy> output_surface_loop; + scoped_refptr<base::MessageLoopProxy> compositor_impl_side_loop; if (enable) - output_surface_loop = compositor_message_loop_proxy_; + compositor_impl_side_loop = compositor_message_loop_proxy_; else - output_surface_loop = base::MessageLoopProxy::current(); + compositor_impl_side_loop = base::MessageLoopProxy::current(); - compositor_output_surface_filter_ = - CompositorOutputSurface::CreateFilter(output_surface_loop.get()); - AddFilter(compositor_output_surface_filter_.get()); + compositor_message_filter_ = new CompositorForwardingMessageFilter( + compositor_impl_side_loop.get()); + AddFilter(compositor_message_filter_.get()); RenderThreadImpl::RegisterSchemes(); diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 28e5943..35730c2 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -52,7 +52,6 @@ class ContextProvider; } namespace IPC { -class ForwardingMessageFilter; class MessageFilter; } @@ -79,6 +78,7 @@ class AecDumpMessageFilter; class AudioInputMessageFilter; class AudioMessageFilter; class AudioRendererMixerManager; +class CompositorForwardingMessageFilter; class ContextProviderCommandBuffer; class DBMessageFilter; class DevToolsAgentFilter; @@ -211,8 +211,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, return main_thread_compositor_task_runner_; } - IPC::ForwardingMessageFilter* compositor_output_surface_filter() const { - return compositor_output_surface_filter_.get(); + CompositorForwardingMessageFilter* compositor_message_filter() const { + return compositor_message_filter_.get(); } InputHandlerManager* input_handler_manager() const { @@ -548,7 +548,7 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, // May be null if unused by the |input_handler_manager_|. scoped_refptr<InputEventFilter> input_event_filter_; scoped_ptr<InputHandlerManager> input_handler_manager_; - scoped_refptr<IPC::ForwardingMessageFilter> compositor_output_surface_filter_; + scoped_refptr<CompositorForwardingMessageFilter> compositor_message_filter_; scoped_refptr<webkit::gpu::ContextProviderWebContext> shared_main_thread_contexts_; diff --git a/content/test/web_layer_tree_view_impl_for_testing.cc b/content/test/web_layer_tree_view_impl_for_testing.cc index cc9b28a..e2cd55a 100644 --- a/content/test/web_layer_tree_view_impl_for_testing.cc +++ b/content/test/web_layer_tree_view_impl_for_testing.cc @@ -11,6 +11,7 @@ #include "cc/blink/web_layer_impl.h" #include "cc/input/input_handler.h" #include "cc/layers/layer.h" +#include "cc/scheduler/begin_frame_source.h" #include "cc/test/pixel_test_output_surface.h" #include "cc/test/test_context_provider.h" #include "cc/trees/layer_tree_host.h" @@ -43,7 +44,13 @@ void WebLayerTreeViewImplForTesting::Initialize() { // Accelerated animations are enabled for unit tests. settings.accelerated_animation_enabled = true; layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded( - this, this, NULL, NULL, settings, base::MessageLoopProxy::current()); + this, + this, + nullptr, + nullptr, + settings, + base::MessageLoopProxy::current(), + nullptr); DCHECK(layer_tree_host_); } diff --git a/mojo/services/html_viewer/weblayertreeview_impl.cc b/mojo/services/html_viewer/weblayertreeview_impl.cc index d92492b..1f025a9 100644 --- a/mojo/services/html_viewer/weblayertreeview_impl.cc +++ b/mojo/services/html_viewer/weblayertreeview_impl.cc @@ -8,6 +8,7 @@ #include "cc/blink/web_layer_impl.h" #include "cc/layers/layer.h" #include "cc/output/begin_frame_args.h" +#include "cc/scheduler/begin_frame_source.h" #include "cc/trees/layer_tree_host.h" #include "mojo/cc/context_provider_mojo.h" #include "mojo/cc/output_surface_mojo.h" @@ -47,7 +48,8 @@ WebLayerTreeViewImpl::WebLayerTreeViewImpl( gpu_memory_buffer_manager, settings, base::MessageLoopProxy::current(), - compositor_message_loop_proxy); + compositor_message_loop_proxy, + nullptr); DCHECK(layer_tree_host_); } diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 35443f4..e85c579 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc @@ -20,6 +20,7 @@ #include "cc/layers/layer.h" #include "cc/output/begin_frame_args.h" #include "cc/output/context_provider.h" +#include "cc/scheduler/begin_frame_source.h" #include "cc/surfaces/surface_id_allocator.h" #include "cc/trees/layer_tree_host.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -144,7 +145,8 @@ Compositor::Compositor(gfx::AcceleratedWidget widget, context_factory_->GetGpuMemoryBufferManager(), settings, task_runner_, - compositor_thread_loop_); + compositor_thread_loop_, + nullptr); } else { host_ = cc::LayerTreeHost::CreateSingleThreaded( this, @@ -152,7 +154,8 @@ Compositor::Compositor(gfx::AcceleratedWidget widget, context_factory_->GetSharedBitmapManager(), context_factory_->GetGpuMemoryBufferManager(), settings, - task_runner_); + task_runner_, + nullptr); } UMA_HISTOGRAM_TIMES("GPU.CreateBrowserCompositor", base::TimeTicks::Now() - before_create); |