diff options
author | skyostil@chromium.org <skyostil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-26 22:28:45 +0000 |
---|---|---|
committer | skyostil@chromium.org <skyostil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-26 22:28:45 +0000 |
commit | 7ed4751b7860f7248ae7042465d3051867632c56 (patch) | |
tree | 4d2fc3b6525453b48461ceeae0611e21c4759648 /cc | |
parent | 5b409ba35802ce8eba4b3056c5787cf73f81c745 (diff) | |
download | chromium_src-7ed4751b7860f7248ae7042465d3051867632c56.zip chromium_src-7ed4751b7860f7248ae7042465d3051867632c56.tar.gz chromium_src-7ed4751b7860f7248ae7042465d3051867632c56.tar.bz2 |
cc: Hook vsync time source to output surface
Let the output surface generate a vsync signal for the vsync time
source. This will be used to drive rendering based on a vsync
notification from the browser process.
BUG=149227
TEST=LayerTreeHostTestVSyncNotification
Review URL: https://chromiumcodereview.appspot.com/12674030
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@190780 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r-- | cc/output/output_surface.h | 5 | ||||
-rw-r--r-- | cc/output/output_surface_client.h | 1 | ||||
-rw-r--r-- | cc/scheduler/vsync_time_source.cc | 2 | ||||
-rw-r--r-- | cc/scheduler/vsync_time_source.h | 2 | ||||
-rw-r--r-- | cc/scheduler/vsync_time_source_unittest.cc | 2 | ||||
-rw-r--r-- | cc/test/fake_layer_tree_host_impl_client.h | 1 | ||||
-rw-r--r-- | cc/test/fake_output_surface.cc | 13 | ||||
-rw-r--r-- | cc/test/fake_output_surface.h | 8 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.cc | 9 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.h | 3 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl_unittest.cc | 1 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest.cc | 51 | ||||
-rw-r--r-- | cc/trees/single_thread_proxy.h | 1 | ||||
-rw-r--r-- | cc/trees/thread_proxy.cc | 32 | ||||
-rw-r--r-- | cc/trees/thread_proxy.h | 10 |
15 files changed, 133 insertions, 8 deletions
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h index ce425ed..bb473e2 100644 --- a/cc/output/output_surface.h +++ b/cc/output/output_surface.h @@ -91,6 +91,11 @@ class CC_EXPORT OutputSurface { // processing should be stopped, or lowered in priority. virtual void UpdateSmoothnessTakesPriority(bool prefer_smoothness) {} + // Requests a vsync notification from the output surface. The notification + // will be delivered by calling OutputSurfaceClient::DidVSync for all future + // vsync events until the callback is disabled. + virtual void EnableVSyncNotification(bool enable_vsync) {} + protected: OutputSurfaceClient* client_; struct cc::OutputSurface::Capabilities capabilities_; diff --git a/cc/output/output_surface_client.h b/cc/output/output_surface_client.h index b8d0ad7..1ba5a43 100644 --- a/cc/output/output_surface_client.h +++ b/cc/output/output_surface_client.h @@ -16,6 +16,7 @@ class CC_EXPORT OutputSurfaceClient { public: virtual void OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) = 0; + virtual void DidVSync(base::TimeTicks frame_time) = 0; virtual void OnSendFrameToParentCompositorAck(const CompositorFrameAck&) = 0; protected: diff --git a/cc/scheduler/vsync_time_source.cc b/cc/scheduler/vsync_time_source.cc index 5f2992e..1483478 100644 --- a/cc/scheduler/vsync_time_source.cc +++ b/cc/scheduler/vsync_time_source.cc @@ -6,7 +6,7 @@ namespace cc { -scoped_refptr<VSyncTimeSource> VSyncTimeSource::create( +scoped_refptr<VSyncTimeSource> VSyncTimeSource::Create( VSyncProvider* vsync_provider) { return make_scoped_refptr(new VSyncTimeSource(vsync_provider)); } diff --git a/cc/scheduler/vsync_time_source.h b/cc/scheduler/vsync_time_source.h index e62e0fb..910168f 100644 --- a/cc/scheduler/vsync_time_source.h +++ b/cc/scheduler/vsync_time_source.h @@ -33,7 +33,7 @@ class VSyncProvider { // external vsync signal. class CC_EXPORT VSyncTimeSource : public TimeSource, public VSyncClient { public: - static scoped_refptr<VSyncTimeSource> create(VSyncProvider* vsync_provider); + static scoped_refptr<VSyncTimeSource> Create(VSyncProvider* vsync_provider); // TimeSource implementation virtual void SetClient(TimeSourceClient* client) OVERRIDE; diff --git a/cc/scheduler/vsync_time_source_unittest.cc b/cc/scheduler/vsync_time_source_unittest.cc index 334dde7..d652017 100644 --- a/cc/scheduler/vsync_time_source_unittest.cc +++ b/cc/scheduler/vsync_time_source_unittest.cc @@ -32,7 +32,7 @@ class FakeVSyncProvider : public VSyncProvider { class VSyncTimeSourceTest : public testing::Test { public: - VSyncTimeSourceTest() : timer_(VSyncTimeSource::create(&provider_)) { + VSyncTimeSourceTest() : timer_(VSyncTimeSource::Create(&provider_)) { timer_->SetClient(&client_); } diff --git a/cc/test/fake_layer_tree_host_impl_client.h b/cc/test/fake_layer_tree_host_impl_client.h index 4ed6442..61555bb 100644 --- a/cc/test/fake_layer_tree_host_impl_client.h +++ b/cc/test/fake_layer_tree_host_impl_client.h @@ -17,6 +17,7 @@ class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient { virtual void OnVSyncParametersChanged( base::TimeTicks, base::TimeDelta) OVERRIDE {} + virtual void DidVSync(base::TimeTicks frame_time) OVERRIDE {} virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {} virtual void OnHasPendingTreeStateChanged(bool has_pending_tree) OVERRIDE {} virtual void SetNeedsRedrawOnImplThread() OVERRIDE {} diff --git a/cc/test/fake_output_surface.cc b/cc/test/fake_output_surface.cc index 0b9a6d3..6369f61 100644 --- a/cc/test/fake_output_surface.cc +++ b/cc/test/fake_output_surface.cc @@ -4,12 +4,15 @@ #include "cc/test/fake_output_surface.h" +#include "cc/output/output_surface_client.h" + namespace cc { FakeOutputSurface::FakeOutputSurface( scoped_ptr<WebKit::WebGraphicsContext3D> context3d, bool has_parent) : OutputSurface(context3d.Pass()), - num_sent_frames_(0) { + num_sent_frames_(0), + vsync_notification_enabled_(false) { capabilities_.has_parent_compositor = has_parent; } @@ -37,4 +40,12 @@ void FakeOutputSurface::SendFrameToParentCompositor( ++num_sent_frames_; } +void FakeOutputSurface::EnableVSyncNotification(bool enable) { + vsync_notification_enabled_ = enable; +} + +void FakeOutputSurface::DidVSync(base::TimeTicks frame_time) { + client_->DidVSync(frame_time); +} + } // namespace cc diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h index 8a2217b..e23f8cb 100644 --- a/cc/test/fake_output_surface.h +++ b/cc/test/fake_output_surface.h @@ -5,6 +5,7 @@ #ifndef CC_TEST_FAKE_OUTPUT_SURFACE_H_ #define CC_TEST_FAKE_OUTPUT_SURFACE_H_ +#include "base/time.h" #include "cc/output/compositor_frame.h" #include "cc/output/output_surface.h" #include "cc/output/software_output_device.h" @@ -61,6 +62,12 @@ class FakeOutputSurface : public OutputSurface { CompositorFrame& last_sent_frame() { return last_sent_frame_; } size_t num_sent_frames() { return num_sent_frames_; } + virtual void EnableVSyncNotification(bool enable) OVERRIDE; + bool vsync_notification_enabled() const { + return vsync_notification_enabled_; + } + void DidVSync(base::TimeTicks frame_time); + private: FakeOutputSurface( scoped_ptr<WebKit::WebGraphicsContext3D> context3d, @@ -72,6 +79,7 @@ class FakeOutputSurface : public OutputSurface { CompositorFrame last_sent_frame_; size_t num_sent_frames_; + bool vsync_notification_enabled_; }; static inline scoped_ptr<cc::OutputSurface> CreateFakeOutputSurface() { diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index a6f15db..3332839 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -915,6 +915,10 @@ void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase, client_->OnVSyncParametersChanged(timebase, interval); } +void LayerTreeHostImpl::DidVSync(base::TimeTicks frame_time) { + client_->DidVSync(frame_time); +} + void LayerTreeHostImpl::OnSendFrameToParentCompositorAck( const CompositorFrameAck& ack) { if (!renderer_) @@ -1039,6 +1043,11 @@ bool LayerTreeHostImpl::SwapBuffers() { return renderer_->SwapBuffers(); } +void LayerTreeHostImpl::EnableVSyncNotification(bool enable) { + if (output_surface_) + output_surface_->EnableVSyncNotification(enable); +} + gfx::Size LayerTreeHostImpl::DeviceViewportSize() const { return device_viewport_size(); } diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 6ef2f64..3025832 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -51,6 +51,7 @@ class LayerTreeHostImplClient { virtual void OnSwapBuffersCompleteOnImplThread() = 0; virtual void OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) = 0; + virtual void DidVSync(base::TimeTicks frame_time) = 0; virtual void OnCanDrawStateChanged(bool can_draw) = 0; virtual void OnHasPendingTreeStateChanged(bool has_pending_tree) = 0; virtual void SetNeedsRedrawOnImplThread() = 0; @@ -182,6 +183,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandlerClient, // OutputSurfaceClient implementation. virtual void OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) OVERRIDE; + virtual void DidVSync(base::TimeTicks frame_time) OVERRIDE; virtual void OnSendFrameToParentCompositorAck(const CompositorFrameAck& ack) OVERRIDE; @@ -205,6 +207,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandlerClient, const RendererCapabilities& GetRendererCapabilities() const; virtual bool SwapBuffers(); + void EnableVSyncNotification(bool enable); void Readback(void* pixels, gfx::Rect rect_in_device_viewport); diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index e47e311..aeca5de 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -91,6 +91,7 @@ class LayerTreeHostImplTest : public testing::Test, virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {} virtual void OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) OVERRIDE {} + virtual void DidVSync(base::TimeTicks frame_time) OVERRIDE {} virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE { on_can_draw_state_changed_called_ = true; } diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 4f7d2d6..eeddab3 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -2164,5 +2164,56 @@ class LayerTreeHostTestLCDNotification : public LayerTreeHostTest { SINGLE_THREAD_TEST_F(LayerTreeHostTestLCDNotification); +// Verify that the vsync notification is used to initiate rendering. +class LayerTreeHostTestVSyncNotification : public LayerTreeHostTest { + public: + virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE { + settings->render_vsync_notification_enabled = true; + } + + virtual void BeginTest() OVERRIDE { + PostSetNeedsCommitToMainThread(); + } + + virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + FakeOutputSurface* fake_output_surface = + reinterpret_cast<FakeOutputSurface*>(host_impl->output_surface()); + + // The vsync notification is turned off now but will get enabled once we + // return, so post a task to trigger it. + ASSERT_FALSE(fake_output_surface->vsync_notification_enabled()); + PostVSyncOnImplThread(fake_output_surface); + } + + void PostVSyncOnImplThread(FakeOutputSurface* fake_output_surface) { + DCHECK(ImplThread()); + ImplThread()->PostTask( + base::Bind(&LayerTreeHostTestVSyncNotification::DidVSync, + base::Unretained(this), + base::Unretained(fake_output_surface))); + } + + void DidVSync(FakeOutputSurface* fake_output_surface) { + ASSERT_TRUE(fake_output_surface->vsync_notification_enabled()); + fake_output_surface->DidVSync(frame_time_); + } + + virtual bool PrepareToDrawOnThread( + LayerTreeHostImpl* host_impl, + LayerTreeHostImpl::FrameData* frame, + bool result) OVERRIDE { + EndTest(); + return true; + } + + virtual void AfterTest() OVERRIDE { + } + + private: + base::TimeTicks frame_time_; +}; + +MULTI_THREAD_TEST_F(LayerTreeHostTestVSyncNotification); + } // namespace } // namespace cc diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h index ea6b549..2322d76 100644 --- a/cc/trees/single_thread_proxy.h +++ b/cc/trees/single_thread_proxy.h @@ -56,6 +56,7 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient { virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE; virtual void OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) OVERRIDE {} + virtual void DidVSync(base::TimeTicks frame_time) OVERRIDE {} virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {} virtual void OnHasPendingTreeStateChanged(bool have_pending_tree) OVERRIDE; virtual void SetNeedsRedrawOnImplThread() OVERRIDE; diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index c49527d..8c7d9de 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc @@ -16,6 +16,7 @@ #include "cc/scheduler/delay_based_time_source.h" #include "cc/scheduler/frame_rate_controller.h" #include "cc/scheduler/scheduler.h" +#include "cc/scheduler/vsync_time_source.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" @@ -59,6 +60,9 @@ ThreadProxy::ThreadProxy(LayerTreeHost* layer_tree_host, texture_acquisition_completion_event_on_impl_thread_(NULL), next_frame_is_newly_committed_frame_on_impl_thread_(false), render_vsync_enabled_(layer_tree_host->settings().render_vsync_enabled), + render_vsync_notification_enabled_( + layer_tree_host->settings().render_vsync_notification_enabled), + vsync_client_(NULL), inside_draw_(false), defer_commits_(false), renew_tree_priority_on_impl_thread_pending_(false) { @@ -350,6 +354,21 @@ void ThreadProxy::OnVSyncParametersChanged(base::TimeTicks timebase, scheduler_on_impl_thread_->SetTimebaseAndInterval(timebase, interval); } +void ThreadProxy::DidVSync(base::TimeTicks frame_time) { + DCHECK(IsImplThread()); + TRACE_EVENT0("cc", "ThreadProxy::DidVSync"); + if (vsync_client_) + vsync_client_->DidVSync(frame_time); +} + +void ThreadProxy::RequestVSyncNotification(VSyncClient* client) { + DCHECK(IsImplThread()); + TRACE_EVENT1( + "cc", "ThreadProxy::RequestVSyncNotification", "enable", !!client); + vsync_client_ = client; + layer_tree_host_impl_->EnableVSyncNotification(client); +} + void ThreadProxy::OnCanDrawStateChanged(bool can_draw) { DCHECK(IsImplThread()); TRACE_EVENT1( @@ -1067,9 +1086,14 @@ void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion, 60); scoped_ptr<FrameRateController> frame_rate_controller; if (render_vsync_enabled_) { - frame_rate_controller.reset( - new FrameRateController(DelayBasedTimeSource::Create( - display_refresh_interval, Proxy::ImplThread()))); + if (render_vsync_notification_enabled_) { + frame_rate_controller.reset( + new FrameRateController(VSyncTimeSource::Create(this))); + } else { + frame_rate_controller.reset( + new FrameRateController(DelayBasedTimeSource::Create( + display_refresh_interval, Proxy::ImplThread()))); + } } else { frame_rate_controller.reset(new FrameRateController(Proxy::ImplThread())); } @@ -1128,10 +1152,12 @@ void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) { DCHECK(IsImplThread()); layer_tree_host_->DeleteContentsTexturesOnImplThread( layer_tree_host_impl_->resource_provider()); + layer_tree_host_impl_->EnableVSyncNotification(false); input_handler_on_impl_thread_.reset(); layer_tree_host_impl_.reset(); scheduler_on_impl_thread_.reset(); weak_factory_on_impl_thread_.InvalidateWeakPtrs(); + vsync_client_ = NULL; completion->Signal(); } diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h index 67084a6..73193aa 100644 --- a/cc/trees/thread_proxy.h +++ b/cc/trees/thread_proxy.h @@ -12,6 +12,7 @@ #include "cc/base/completion_event.h" #include "cc/resources/resource_update_controller.h" #include "cc/scheduler/scheduler.h" +#include "cc/scheduler/vsync_time_source.h" #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/proxy.h" @@ -28,7 +29,8 @@ class Thread; class ThreadProxy : public Proxy, LayerTreeHostImplClient, SchedulerClient, - ResourceUpdateControllerClient { + ResourceUpdateControllerClient, + VSyncProvider { public: static scoped_ptr<Proxy> Create(LayerTreeHost* layer_tree_host, scoped_ptr<Thread> impl_thread); @@ -69,6 +71,7 @@ class ThreadProxy : public Proxy, virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE; virtual void OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval) OVERRIDE; + virtual void DidVSync(base::TimeTicks frame_time) OVERRIDE; virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE; virtual void OnHasPendingTreeStateChanged(bool has_pending_tree) OVERRIDE; virtual void SetNeedsRedrawOnImplThread() OVERRIDE; @@ -104,6 +107,9 @@ class ThreadProxy : public Proxy, // ResourceUpdateControllerClient implementation virtual void ReadyToFinalizeTextureUpdates() OVERRIDE; + // VSyncProvider implementation + virtual void RequestVSyncNotification(VSyncClient* client) OVERRIDE; + int MaxFramesPendingForTesting() const { return scheduler_on_impl_thread_->MaxFramesPending(); } @@ -248,6 +254,8 @@ class ThreadProxy : public Proxy, bool next_frame_is_newly_committed_frame_on_impl_thread_; bool render_vsync_enabled_; + bool render_vsync_notification_enabled_; + VSyncClient* vsync_client_; bool inside_draw_; |