From e627c5239eed0c99cbb7c9973d9241c125aaaed3 Mon Sep 17 00:00:00 2001 From: dbeam Date: Mon, 4 May 2015 20:25:52 -0700 Subject: [PATCH] Revert of Enable BeginFrame scheduling on aura (patchset #15 id:270001 of https://codereview.chromium.org/1016033006/) Reason for revert: Making Autofill interactive tests incredibly flaky again: http://build.chromium.org/p/chromium.chromiumos/builders/Linux%20ChromiumOS%20Tests%20(1) http://build.chromium.org/p/chromium.chromiumos/builders/Linux%20ChromiumOS%20Ozone%20Tests%20%281%29/ Original issue's description: > Enable BeginFrame scheduling on aura > > This cl is last partial cl from https://codereview.chromium.org/775143003/ > for easy review. > Until now, BeginFrame is initiated by each renderer process. > With this cl, BeginFrame is scheduled from parent(browser) cc scheduler > to child(renderer) cc scheduler. > For more detailed information, please see this (http://goo.gl/D1Qxrr) > > Also, --enable-begin-frame-scheduling is no longer needed because all platform except Mac > uses it as a default. > > R=brianderson@chromium.org, danakj@chromium.org, mithro@mithis.com > BUG=372086 > > Committed: https://crrev.com/17dd2f109f3155ebf183627b63df25f97f34b67f > Cr-Commit-Position: refs/heads/master@{#322622} > > Committed: https://crrev.com/62a759e582743bca13f27d1ce5db3dc2fe66fbb6 > Cr-Commit-Position: refs/heads/master@{#328170} TBR=brianderson@chromium.org,danakj@chromium.org,mithro@mithis.com,sievers@chromium.org,oshima@chromium.org,boliu@chromium.org,simonhong@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=372086 Review URL: https://codereview.chromium.org/1124523003 Cr-Commit-Position: refs/heads/master@{#328267} --- android_webview/lib/main/aw_main_delegate.cc | 1 + ash/display/display_controller.cc | 7 +- .../chromeos/login/chrome_restart_request.cc | 1 + .../browser/android/content_startup_flags.cc | 2 + .../browser_compositor_output_surface.cc | 27 +++++++- .../browser_compositor_output_surface.h | 17 ++++- .../compositor/delegated_frame_host.cc | 16 ++++- .../browser/compositor/delegated_frame_host.h | 16 ++++- .../gpu_browser_compositor_output_surface.cc | 2 + .../gpu_browser_compositor_output_surface.h | 5 ++ .../gpu_process_transport_factory.cc | 9 +-- ...eless_browser_compositor_output_surface.cc | 2 + ...celess_browser_compositor_output_surface.h | 1 + ...creen_browser_compositor_output_surface.cc | 2 + ...screen_browser_compositor_output_surface.h | 5 ++ .../compositor/reflector_impl_unittest.cc | 10 ++- ...tware_browser_compositor_output_surface.cc | 6 +- ...ftware_browser_compositor_output_surface.h | 7 +- ...wser_compositor_output_surface_unittest.cc | 4 +- .../begin_frame_observer_proxy.cc | 8 --- .../begin_frame_observer_proxy.h | 14 +--- .../renderer_host/render_process_host_impl.cc | 1 + .../render_widget_host_view_aura.cc | 22 ++----- .../render_widget_host_view_aura.h | 13 +--- .../render_widget_host_view_mac.h | 3 + .../render_widget_host_view_mac.mm | 6 ++ content/public/common/content_switches.cc | 3 + content/public/common/content_switches.h | 1 + .../renderer/gpu/render_widget_compositor.cc | 5 +- ui/compositor/BUILD.gn | 2 + ui/compositor/compositor.cc | 7 +- ui/compositor/compositor.gyp | 2 + ui/compositor/compositor.h | 14 ++-- ui/compositor/compositor_vsync_manager.cc | 46 +++++++++++++ ui/compositor/compositor_vsync_manager.h | 65 +++++++++++++++++++ 35 files changed, 269 insertions(+), 83 deletions(-) create mode 100644 ui/compositor/compositor_vsync_manager.cc create mode 100644 ui/compositor/compositor_vsync_manager.h diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc index 49cc4dd379b949..852081619f39e6 100644 --- a/android_webview/lib/main/aw_main_delegate.cc +++ b/android_webview/lib/main/aw_main_delegate.cc @@ -60,6 +60,7 @@ bool AwMainDelegate::BasicStartupComplete(int* exit_code) { BrowserViewRenderer::CalculateTileMemoryPolicy(); base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); + cl->AppendSwitch(switches::kEnableBeginFrameScheduling); // WebView uses the Android system's scrollbars and overscroll glow. cl->AppendSwitch(switches::kDisableOverscrollEdgeEffect); diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc index 1a8ab36966865b..e28472e09f3fe9 100644 --- a/ash/display/display_controller.cc +++ b/ash/display/display_controller.cc @@ -37,6 +37,7 @@ #include "ui/aura/window_tracker.h" #include "ui/aura/window_tree_host.h" #include "ui/compositor/compositor.h" +#include "ui/compositor/compositor_vsync_manager.h" #include "ui/gfx/display.h" #include "ui/gfx/screen.h" #include "ui/wm/core/coordinate_conversion.h" @@ -150,9 +151,9 @@ void SetDisplayPropertiesOnHost(AshWindowTreeHost* ash_host, DisplayMode mode = GetDisplayManager()->GetActiveModeForDisplayId(display.id()); if (mode.refresh_rate > 0.0f) { - host->compositor()->SetAuthoritativeVSyncInterval( - base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond / - mode.refresh_rate)); + host->compositor()->vsync_manager()->SetAuthoritativeVSyncInterval( + base::TimeDelta::FromMicroseconds( + base::Time::kMicrosecondsPerSecond / mode.refresh_rate)); } // Just movnig the display requires the full redraw. diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index e76c53242c841e..bf31bf3573e7e6 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc @@ -96,6 +96,7 @@ std::string DeriveCommandLine(const GURL& start_url, ::switches::kDisableThreadedScrolling, ::switches::kDisableTouchDragDrop, ::switches::kDisableTouchEditing, + ::switches::kEnableBeginFrameScheduling, ::switches::kEnableBlinkFeatures, ::switches::kEnableCompositorAnimationTimelines, ::switches::kEnableDelegatedRenderer, diff --git a/content/browser/android/content_startup_flags.cc b/content/browser/android/content_startup_flags.cc index 93426d8a0676dd..e679825518068d 100644 --- a/content/browser/android/content_startup_flags.cc +++ b/content/browser/android/content_startup_flags.cc @@ -54,6 +54,8 @@ void SetContentCommandLineFlags(bool single_process, parsed_command_line->AppendSwitch(switches::kSingleProcess); } + parsed_command_line->AppendSwitch(switches::kEnableBeginFrameScheduling); + parsed_command_line->AppendSwitch(switches::kEnablePinch); parsed_command_line->AppendSwitch(switches::kEnableOverlayFullscreenVideo); parsed_command_line->AppendSwitch(switches::kEnableOverlayScrollbar); diff --git a/content/browser/compositor/browser_compositor_output_surface.cc b/content/browser/compositor/browser_compositor_output_surface.cc index a7181842ce6d0d..6839457196ed4e 100644 --- a/content/browser/compositor/browser_compositor_output_surface.cc +++ b/content/browser/compositor/browser_compositor_output_surface.cc @@ -15,17 +15,21 @@ namespace content { BrowserCompositorOutputSurface::BrowserCompositorOutputSurface( const scoped_refptr& context_provider, + const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator) : OutputSurface(context_provider), + vsync_manager_(vsync_manager), reflector_(nullptr) { overlay_candidate_validator_ = overlay_candidate_validator.Pass(); Initialize(); } BrowserCompositorOutputSurface::BrowserCompositorOutputSurface( - scoped_ptr software_device) + scoped_ptr software_device, + const scoped_refptr& vsync_manager) : OutputSurface(software_device.Pass()), + vsync_manager_(vsync_manager), reflector_(nullptr) { Initialize(); } @@ -34,6 +38,9 @@ BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() { if (reflector_) reflector_->DetachFromOutputSurface(); DCHECK(!reflector_); + if (!HasClient()) + return; + vsync_manager_->RemoveObserver(this); } void BrowserCompositorOutputSurface::Initialize() { @@ -41,13 +48,29 @@ void BrowserCompositorOutputSurface::Initialize() { capabilities_.adjust_deadline_for_parent = false; } -void BrowserCompositorOutputSurface::OnUpdateVSyncParametersFromGpu( +bool BrowserCompositorOutputSurface::BindToClient( + cc::OutputSurfaceClient* client) { + if (!OutputSurface::BindToClient(client)) + return false; + // Don't want vsync notifications until there is a client. + vsync_manager_->AddObserver(this); + return true; +} + +void BrowserCompositorOutputSurface::OnUpdateVSyncParameters( base::TimeTicks timebase, base::TimeDelta interval) { DCHECK(HasClient()); CommitVSyncParameters(timebase, interval); } +void BrowserCompositorOutputSurface::OnUpdateVSyncParametersFromGpu( + base::TimeTicks timebase, + base::TimeDelta interval) { + DCHECK(HasClient()); + vsync_manager_->UpdateVSyncParameters(timebase, interval); +} + void BrowserCompositorOutputSurface::SetReflector(ReflectorImpl* reflector) { // Software mirroring is done by doing a GL copy out of the framebuffer - if // we have overlays then that data will be missing. diff --git a/content/browser/compositor/browser_compositor_output_surface.h b/content/browser/compositor/browser_compositor_output_surface.h index dc63b68a88b7a3..615a54e30c5ab9 100644 --- a/content/browser/compositor/browser_compositor_output_surface.h +++ b/content/browser/compositor/browser_compositor_output_surface.h @@ -8,6 +8,7 @@ #include "base/threading/non_thread_safe.h" #include "cc/output/output_surface.h" #include "content/common/content_export.h" +#include "ui/compositor/compositor_vsync_manager.h" namespace cc { class SoftwareOutputDevice; @@ -20,12 +21,19 @@ class ReflectorImpl; class WebGraphicsContext3DCommandBufferImpl; class CONTENT_EXPORT BrowserCompositorOutputSurface - : public cc::OutputSurface { + : public cc::OutputSurface, + public ui::CompositorVSyncManager::Observer { public: ~BrowserCompositorOutputSurface() override; + // cc::OutputSurface implementation. + bool BindToClient(cc::OutputSurfaceClient* client) override; cc::OverlayCandidateValidator* GetOverlayCandidateValidator() const override; + // ui::CompositorOutputSurface::Observer implementation. + void OnUpdateVSyncParameters(base::TimeTicks timebase, + base::TimeDelta interval) override; + void OnUpdateVSyncParametersFromGpu(base::TimeTicks tiembase, base::TimeDelta interval); @@ -41,13 +49,16 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface // Constructor used by the accelerated implementation. BrowserCompositorOutputSurface( const scoped_refptr& context, + const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator); // Constructor used by the software implementation. - explicit BrowserCompositorOutputSurface( - scoped_ptr software_device); + BrowserCompositorOutputSurface( + scoped_ptr software_device, + const scoped_refptr& vsync_manager); + scoped_refptr vsync_manager_; ReflectorImpl* reflector_; private: diff --git a/content/browser/compositor/delegated_frame_host.cc b/content/browser/compositor/delegated_frame_host.cc index 98d7ac172c0a69..f45e7f40c1c302 100644 --- a/content/browser/compositor/delegated_frame_host.cc +++ b/content/browser/compositor/delegated_frame_host.cc @@ -888,10 +888,13 @@ void DelegatedFrameHost::OnCompositingShuttingDown(ui::Compositor* compositor) { DCHECK(!compositor_); } -void DelegatedFrameHost::SetVSyncParameters(base::TimeTicks timebase, - base::TimeDelta interval) { +void DelegatedFrameHost::OnUpdateVSyncParameters( + base::TimeTicks timebase, + base::TimeDelta interval) { vsync_timebase_ = timebase; vsync_interval_ = interval; + if (client_->DelegatedFrameHostIsVisible()) + client_->DelegatedFrameHostUpdateVSyncParameters(timebase, interval); } //////////////////////////////////////////////////////////////////////////////// @@ -917,6 +920,8 @@ DelegatedFrameHost::~DelegatedFrameHost() { surface_factory_->Destroy(surface_id_); if (resource_collection_.get()) resource_collection_->SetClient(NULL); + + DCHECK(!vsync_manager_.get()); } void DelegatedFrameHost::RunOnCommitCallbacks() { @@ -943,6 +948,9 @@ void DelegatedFrameHost::SetCompositor(ui::Compositor* compositor) { return; compositor_ = compositor; compositor_->AddObserver(this); + DCHECK(!vsync_manager_.get()); + vsync_manager_ = compositor_->vsync_manager(); + vsync_manager_->AddObserver(this); } void DelegatedFrameHost::ResetCompositor() { @@ -955,6 +963,10 @@ void DelegatedFrameHost::ResetCompositor() { } if (compositor_->HasObserver(this)) compositor_->RemoveObserver(this); + if (vsync_manager_.get()) { + vsync_manager_->RemoveObserver(this); + vsync_manager_ = NULL; + } compositor_ = nullptr; } diff --git a/content/browser/compositor/delegated_frame_host.h b/content/browser/compositor/delegated_frame_host.h index 917623ef506f02..f208c267e3f2ea 100644 --- a/content/browser/compositor/delegated_frame_host.h +++ b/content/browser/compositor/delegated_frame_host.h @@ -18,6 +18,7 @@ #include "content/public/browser/render_process_host.h" #include "ui/compositor/compositor.h" #include "ui/compositor/compositor_observer.h" +#include "ui/compositor/compositor_vsync_manager.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_owner_delegate.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -60,6 +61,10 @@ class CONTENT_EXPORT DelegatedFrameHostClient { int output_surface_id, const cc::CompositorFrameAck& ack) = 0; virtual void DelegatedFrameHostOnLostCompositorResources() = 0; + + virtual void DelegatedFrameHostUpdateVSyncParameters( + const base::TimeTicks& timebase, + const base::TimeDelta& interval) = 0; }; // The DelegatedFrameHost is used to host all of the RenderWidgetHostView state @@ -68,6 +73,7 @@ class CONTENT_EXPORT DelegatedFrameHostClient { // the ui::Compositor associated with its DelegatedFrameHostClient. class CONTENT_EXPORT DelegatedFrameHost : public ui::CompositorObserver, + public ui::CompositorVSyncManager::Observer, public ui::LayerOwnerDelegate, public ImageTransportFactoryObserver, public DelegatedFrameEvictorClient, @@ -93,7 +99,6 @@ class CONTENT_EXPORT DelegatedFrameHost gfx::Size GetRequestedRendererSize() const; void SetCompositor(ui::Compositor* compositor); void ResetCompositor(); - void SetVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval); // Note: |src_subset| is specified in DIP dimensions while |output_size| // expects pixels. void CopyFromCompositingSurface(const gfx::Rect& src_subrect, @@ -153,6 +158,10 @@ class CONTENT_EXPORT DelegatedFrameHost void OnCompositingLockStateChanged(ui::Compositor* compositor) override; void OnCompositingShuttingDown(ui::Compositor* compositor) override; + // Overridden from ui::CompositorVSyncManager::Observer: + void OnUpdateVSyncParameters(base::TimeTicks timebase, + base::TimeDelta interval) override; + // Overridden from ui::LayerOwnerObserver: void OnLayerRecreated(ui::Layer* old_layer, ui::Layer* new_layer) override; @@ -234,8 +243,11 @@ class CONTENT_EXPORT DelegatedFrameHost std::vector on_compositing_did_commit_callbacks_; + // The vsync manager we are observing for changes, if any. + scoped_refptr vsync_manager_; + // The current VSync timebase and interval. These are zero until the first - // call to UpdateVSyncParameters(). + // call to OnUpdateVSyncParameters(). base::TimeTicks vsync_timebase_; base::TimeDelta vsync_interval_; diff --git a/content/browser/compositor/gpu_browser_compositor_output_surface.cc b/content/browser/compositor/gpu_browser_compositor_output_surface.cc index b4a259627c23a0..09a8b7280a5501 100644 --- a/content/browser/compositor/gpu_browser_compositor_output_surface.cc +++ b/content/browser/compositor/gpu_browser_compositor_output_surface.cc @@ -18,9 +18,11 @@ namespace content { GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface( const scoped_refptr& context, + const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator) : BrowserCompositorOutputSurface(context, + vsync_manager, overlay_candidate_validator.Pass()), #if defined(OS_MACOSX) should_show_frames_state_(SHOULD_SHOW_FRAMES), diff --git a/content/browser/compositor/gpu_browser_compositor_output_surface.h b/content/browser/compositor/gpu_browser_compositor_output_surface.h index b1c82590951013..2b3d2b76dbf68b 100644 --- a/content/browser/compositor/gpu_browser_compositor_output_surface.h +++ b/content/browser/compositor/gpu_browser_compositor_output_surface.h @@ -8,6 +8,10 @@ #include "base/cancelable_callback.h" #include "content/browser/compositor/browser_compositor_output_surface.h" +namespace ui { +class CompositorVSyncManager; +} + namespace content { class CommandBufferProxyImpl; class BrowserCompositorOverlayCandidateValidator; @@ -20,6 +24,7 @@ class GpuBrowserCompositorOutputSurface public: GpuBrowserCompositorOutputSurface( const scoped_refptr& context, + const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator); diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index 330aaa847d223f..151ba009b06a47 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc @@ -280,12 +280,13 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( scoped_ptr surface; if (!create_gpu_output_surface) { surface = make_scoped_ptr(new SoftwareBrowserCompositorOutputSurface( - CreateSoftwareOutputDevice(compositor.get()))); + CreateSoftwareOutputDevice(compositor.get()), + compositor->vsync_manager())); } else { DCHECK(context_provider); if (!data->surface_id) { surface = make_scoped_ptr(new OffscreenBrowserCompositorOutputSurface( - context_provider, + context_provider, compositor->vsync_manager(), scoped_ptr())); } else #if defined(USE_OZONE) @@ -293,14 +294,14 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( ->CanShowPrimaryPlaneAsOverlay()) { surface = make_scoped_ptr(new GpuSurfacelessBrowserCompositorOutputSurface( - context_provider, data->surface_id, + context_provider, data->surface_id, compositor->vsync_manager(), CreateOverlayCandidateValidator(compositor->widget()), GL_RGB, BrowserGpuMemoryBufferManager::current())); } else #endif { surface = make_scoped_ptr(new GpuBrowserCompositorOutputSurface( - context_provider, + context_provider, compositor->vsync_manager(), CreateOverlayCandidateValidator(compositor->widget()))); } } diff --git a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc index 041a41ca32523c..ff77fa946649f4 100644 --- a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc +++ b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc @@ -20,11 +20,13 @@ GpuSurfacelessBrowserCompositorOutputSurface:: GpuSurfacelessBrowserCompositorOutputSurface( const scoped_refptr& context, int surface_id, + const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator, unsigned internalformat, BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager) : GpuBrowserCompositorOutputSurface(context, + vsync_manager, overlay_candidate_validator.Pass()), internalformat_(internalformat), gpu_memory_buffer_manager_(gpu_memory_buffer_manager) { diff --git a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h index ff66d02b60f2c0..7f634dd2be52f9 100644 --- a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h +++ b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h @@ -19,6 +19,7 @@ class GpuSurfacelessBrowserCompositorOutputSurface GpuSurfacelessBrowserCompositorOutputSurface( const scoped_refptr& context, int surface_id, + const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator, unsigned internalformat, diff --git a/content/browser/compositor/offscreen_browser_compositor_output_surface.cc b/content/browser/compositor/offscreen_browser_compositor_output_surface.cc index 0e528d957ecc3f..9fa502684c7451 100644 --- a/content/browser/compositor/offscreen_browser_compositor_output_surface.cc +++ b/content/browser/compositor/offscreen_browser_compositor_output_surface.cc @@ -29,9 +29,11 @@ namespace content { OffscreenBrowserCompositorOutputSurface:: OffscreenBrowserCompositorOutputSurface( const scoped_refptr& context, + const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator) : BrowserCompositorOutputSurface(context, + vsync_manager, overlay_candidate_validator.Pass()), fbo_(0), is_backbuffer_discarded_(false), diff --git a/content/browser/compositor/offscreen_browser_compositor_output_surface.h b/content/browser/compositor/offscreen_browser_compositor_output_surface.h index 167210193aefd6..e9fbe6d7c5fde8 100644 --- a/content/browser/compositor/offscreen_browser_compositor_output_surface.h +++ b/content/browser/compositor/offscreen_browser_compositor_output_surface.h @@ -9,6 +9,10 @@ #include "base/memory/weak_ptr.h" #include "content/browser/compositor/browser_compositor_output_surface.h" +namespace ui { +class CompositorVSyncManager; +} + namespace content { class CommandBufferProxyImpl; @@ -17,6 +21,7 @@ class OffscreenBrowserCompositorOutputSurface public: OffscreenBrowserCompositorOutputSurface( const scoped_refptr& context, + const scoped_refptr& vsync_manager, scoped_ptr overlay_candidate_validator); diff --git a/content/browser/compositor/reflector_impl_unittest.cc b/content/browser/compositor/reflector_impl_unittest.cc index 231015f24e8b0a..867a9de10a2249 100644 --- a/content/browser/compositor/reflector_impl_unittest.cc +++ b/content/browser/compositor/reflector_impl_unittest.cc @@ -69,9 +69,11 @@ CreateTestValidatorOzone() { class TestOutputSurface : public BrowserCompositorOutputSurface { public: - explicit TestOutputSurface( - const scoped_refptr& context_provider) + TestOutputSurface( + const scoped_refptr& context_provider, + const scoped_refptr& vsync_manager) : BrowserCompositorOutputSurface(context_provider, + vsync_manager, CreateTestValidatorOzone().Pass()) {} void SetFlip(bool flip) { capabilities_.flipped_output_surface = flip; } @@ -111,7 +113,9 @@ class ReflectorImplTest : public testing::Test { context_provider_ = cc::TestContextProvider::Create( cc::TestWebGraphicsContext3D::Create().Pass()); output_surface_ = - scoped_ptr(new TestOutputSurface(context_provider_)); + scoped_ptr( + new TestOutputSurface(context_provider_, + compositor_->vsync_manager())).Pass(); CHECK(output_surface_->BindToClient(&output_surface_client_)); mirroring_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); diff --git a/content/browser/compositor/software_browser_compositor_output_surface.cc b/content/browser/compositor/software_browser_compositor_output_surface.cc index 5e5e9bbfa98bc9..c2b70d40c94bd1 100644 --- a/content/browser/compositor/software_browser_compositor_output_surface.cc +++ b/content/browser/compositor/software_browser_compositor_output_surface.cc @@ -17,8 +17,10 @@ namespace content { SoftwareBrowserCompositorOutputSurface::SoftwareBrowserCompositorOutputSurface( - scoped_ptr software_device) - : BrowserCompositorOutputSurface(software_device.Pass()), + scoped_ptr software_device, + const scoped_refptr& vsync_manager) + : BrowserCompositorOutputSurface(software_device.Pass(), + vsync_manager), weak_factory_(this) { } diff --git a/content/browser/compositor/software_browser_compositor_output_surface.h b/content/browser/compositor/software_browser_compositor_output_surface.h index 520aca8916da22..68776ca7aa653a 100644 --- a/content/browser/compositor/software_browser_compositor_output_surface.h +++ b/content/browser/compositor/software_browser_compositor_output_surface.h @@ -13,13 +13,18 @@ namespace cc { class SoftwareOutputDevice; } +namespace ui { +class CompositorVSyncManager; +} + namespace content { class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface : public BrowserCompositorOutputSurface { public: SoftwareBrowserCompositorOutputSurface( - scoped_ptr software_device); + scoped_ptr software_device, + const scoped_refptr& vsync_manager); ~SoftwareBrowserCompositorOutputSurface() override; diff --git a/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc b/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc index 7dc2e282507dea..68534f0cacd15c 100644 --- a/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc +++ b/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc @@ -104,7 +104,9 @@ scoped_ptr SoftwareBrowserCompositorOutputSurfaceTest::CreateSurface( scoped_ptr device) { return scoped_ptr( - new content::SoftwareBrowserCompositorOutputSurface(device.Pass())); + new content::SoftwareBrowserCompositorOutputSurface( + device.Pass(), + compositor_->vsync_manager())); } TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, NoVSyncProvider) { diff --git a/content/browser/renderer_host/begin_frame_observer_proxy.cc b/content/browser/renderer_host/begin_frame_observer_proxy.cc index 06baa18bd2a128..7a6651f53c3a9f 100644 --- a/content/browser/renderer_host/begin_frame_observer_proxy.cc +++ b/content/browser/renderer_host/begin_frame_observer_proxy.cc @@ -14,7 +14,6 @@ BeginFrameObserverProxy::BeginFrameObserverProxy( } BeginFrameObserverProxy::~BeginFrameObserverProxy() { - DCHECK(!compositor_); } void BeginFrameObserverProxy::SetNeedsBeginFrames(bool needs_begin_frames) { @@ -39,7 +38,6 @@ void BeginFrameObserverProxy::SetCompositor(ui::Compositor* compositor) { DCHECK(compositor); compositor_ = compositor; - compositor_->AddObserver(this); if (needs_begin_frames_) StartObservingBeginFrames(); } @@ -47,7 +45,6 @@ void BeginFrameObserverProxy::SetCompositor(ui::Compositor* compositor) { void BeginFrameObserverProxy::ResetCompositor() { if (!compositor_) return; - compositor_->RemoveObserver(this); if (needs_begin_frames_) StopObservingBeginFrames(); @@ -60,11 +57,6 @@ void BeginFrameObserverProxy::OnSendBeginFrame(const cc::BeginFrameArgs& args) { last_sent_begin_frame_args_ = args; } -void BeginFrameObserverProxy::OnCompositingShuttingDown( - ui::Compositor* compositor) { - ResetCompositor(); -} - void BeginFrameObserverProxy::StartObservingBeginFrames() { DCHECK(compositor_); compositor_->AddBeginFrameObserver(this); diff --git a/content/browser/renderer_host/begin_frame_observer_proxy.h b/content/browser/renderer_host/begin_frame_observer_proxy.h index 291d8bb8a96c51..fd2aa6d7a06f95 100644 --- a/content/browser/renderer_host/begin_frame_observer_proxy.h +++ b/content/browser/renderer_host/begin_frame_observer_proxy.h @@ -25,8 +25,7 @@ class BeginFrameObserverProxyClient { // This class is used to manage all of the RenderWidgetHostView state and // functionality that is associated with BeginFrame message handling. class CONTENT_EXPORT BeginFrameObserverProxy - : public ui::CompositorBeginFrameObserver, - public ui::CompositorObserver { + : public ui::CompositorBeginFrameObserver { public: explicit BeginFrameObserverProxy(BeginFrameObserverProxyClient* client); ~BeginFrameObserverProxy() override; @@ -39,17 +38,6 @@ class CONTENT_EXPORT BeginFrameObserverProxy // Overridden from ui::CompositorBeginFrameObserver: void OnSendBeginFrame(const cc::BeginFrameArgs& args) override; - // Overridden from ui::CompositorObserver: - // TODO(simonhong): Stop overriding ui::CompositorObserver. We need to make - // sure that this class should be destroyed before ui::Compositor. - void OnCompositingDidCommit(ui::Compositor* compositor) override {} - void OnCompositingStarted(ui::Compositor* compositor, - base::TimeTicks start_time) override {} - void OnCompositingEnded(ui::Compositor* compositor) override {} - void OnCompositingAborted(ui::Compositor* compositor) override {} - void OnCompositingLockStateChanged(ui::Compositor* compositor) override {} - void OnCompositingShuttingDown(ui::Compositor* compositor) override; - private: void StartObservingBeginFrames(); void StopObservingBeginFrames(); diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 988e394ffc92e7..25a4fa3bccd99f 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -1240,6 +1240,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( switches::kDisableTouchEditing, switches::kDisableV8IdleTasks, switches::kDomAutomationController, + switches::kEnableBeginFrameScheduling, switches::kEnableBleedingEdgeRenderingFastPaths, switches::kEnableBlinkFeatures, switches::kEnableBrowserSideNavigation, diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index ac035cf2f4e6e4..fd85fcc8745cdf 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -66,6 +66,7 @@ #include "ui/base/hit_test.h" #include "ui/base/ime/input_method.h" #include "ui/base/ui_base_types.h" +#include "ui/compositor/compositor_vsync_manager.h" #include "ui/compositor/dip_util.h" #include "ui/events/blink/blink_event_util.h" #include "ui/events/event.h" @@ -443,7 +444,6 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host, has_snapped_to_boundary_(false), touch_editing_client_(NULL), is_guest_view_hack_(is_guest_view_hack), - begin_frame_observer_proxy_(this), weak_ptr_factory_(this) { if (!is_guest_view_hack_) host_->SetView(this); @@ -473,8 +473,6 @@ bool RenderWidgetHostViewAura::OnMessageReceived( // RenderWidgetHostViewAndroid should also be moved at the same time. IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged, OnTextInputStateChanged) - IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames, - OnSetNeedsBeginFrames) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -704,15 +702,6 @@ ui::TextInputClient* RenderWidgetHostViewAura::GetTextInputClient() { return this; } -void RenderWidgetHostViewAura::OnSetNeedsBeginFrames(bool needs_begin_frames) { - begin_frame_observer_proxy_.SetNeedsBeginFrames(needs_begin_frames); -} - -void RenderWidgetHostViewAura::SendBeginFrame(const cc::BeginFrameArgs& args) { - delegated_frame_host_->SetVSyncParameters(args.frame_time, args.interval); - host_->Send(new ViewMsg_BeginFrame(host_->GetRoutingID(), args)); -} - void RenderWidgetHostViewAura::SetKeyboardFocus() { #if defined(OS_WIN) if (CanFocus()) { @@ -2640,8 +2629,6 @@ void RenderWidgetHostViewAura::AddedToRootWindow() { #endif delegated_frame_host_->SetCompositor(window_->GetHost()->compositor()); - if (window_->GetHost()->compositor()) - begin_frame_observer_proxy_.SetCompositor(window_->GetHost()->compositor()); } void RenderWidgetHostViewAura::RemovingFromRootWindow() { @@ -2654,7 +2641,6 @@ void RenderWidgetHostViewAura::RemovingFromRootWindow() { window_->GetHost()->RemoveObserver(this); delegated_frame_host_->ResetCompositor(); - begin_frame_observer_proxy_.ResetCompositor(); #if defined(OS_WIN) // Update the legacy window's parent temporarily to the desktop window. It @@ -2766,6 +2752,12 @@ void RenderWidgetHostViewAura::DelegatedFrameHostOnLostCompositorResources() { host_->ScheduleComposite(); } +void RenderWidgetHostViewAura::DelegatedFrameHostUpdateVSyncParameters( + const base::TimeTicks& timebase, + const base::TimeDelta& interval) { + host_->UpdateVSyncParameters(timebase, interval); +} + void RenderWidgetHostViewAura::OnDidNavigateMainFrameToNewPage() { ui::GestureRecognizer::Get()->CancelActiveTouches(window_); } diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index f3f6869bf9517b..69fe661283393f 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h @@ -20,7 +20,6 @@ #include "content/browser/compositor/delegated_frame_host.h" #include "content/browser/compositor/image_transport_factory.h" #include "content/browser/compositor/owned_mailbox.h" -#include "content/browser/renderer_host/begin_frame_observer_proxy.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/common/content_export.h" #include "content/common/cursors/webcursor.h" @@ -81,7 +80,6 @@ class RenderWidgetHostView; class CONTENT_EXPORT RenderWidgetHostViewAura : public RenderWidgetHostViewBase, public DelegatedFrameHostClient, - public BeginFrameObserverProxyClient, public ui::TextInputClient, public gfx::DisplayObserver, public aura::WindowTreeHostObserver, @@ -473,9 +471,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAura int output_surface_id, const cc::CompositorFrameAck& ack) override; void DelegatedFrameHostOnLostCompositorResources() override; - - // BeginFrameObserverProxyClient implementation. - void SendBeginFrame(const cc::BeginFrameArgs& args) override; + void DelegatedFrameHostUpdateVSyncParameters( + const base::TimeTicks& timebase, + const base::TimeDelta& interval) override; // Detaches |this| from the input method object. void DetachFromInputMethod(); @@ -498,9 +496,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura // Helper function to set keyboard focus to the main window. void SetKeyboardFocus(); - // Called when RenderWidget wants to start BeginFrame scheduling or stop. - void OnSetNeedsBeginFrames(bool needs_begin_frames); - RenderFrameHostImpl* GetFocusedFrame(); // Returns true if the |event| passed in can be forwarded to the renderer. @@ -675,8 +670,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura // compositing surface and showing the disambiguation popup. gfx::Vector2dF disambiguation_scroll_offset_; - BeginFrameObserverProxy begin_frame_observer_proxy_; - base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAura); }; diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 18fd462d286032..499026922fd9dd 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h @@ -491,6 +491,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac int output_surface_id, const cc::CompositorFrameAck& ack) override; void DelegatedFrameHostOnLostCompositorResources() override; + void DelegatedFrameHostUpdateVSyncParameters( + const base::TimeTicks& timebase, + const base::TimeDelta& interval) override; // AcceleratedWidgetMacNSView implementation. NSView* AcceleratedWidgetGetNSView() const override; diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 0e1e67bff25019..22707f03bb7210 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm @@ -459,6 +459,12 @@ float FlipYFromRectToScreen(float y, float rect_height) { render_widget_host_->ScheduleComposite(); } +void RenderWidgetHostViewMac::DelegatedFrameHostUpdateVSyncParameters( + const base::TimeTicks& timebase, + const base::TimeDelta& interval) { + render_widget_host_->UpdateVSyncParameters(timebase, interval); +} + //////////////////////////////////////////////////////////////////////////////// // AcceleratedWidgetMacNSView, public: diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 29b713f2d042ee..43c7174f4f2c6b 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc @@ -295,6 +295,9 @@ const char kEnableDistanceFieldText[] = "enable-distance-field-text"; // Enable the experimental Credential Manager JavaScript API. const char kEnableCredentialManagerAPI[] = "enable-credential-manager-api"; +// Use a BeginFrame signal from browser to renderer to schedule rendering. +const char kEnableBeginFrameScheduling[] = "enable-begin-frame-scheduling"; + // Enable the creation of compositing layers when it would prevent LCD text. const char kEnablePreferCompositingToLCDText[] = "enable-prefer-compositing-to-lcd-text"; diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index d50bdac510617e..c056b6b8ba41e2 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h @@ -92,6 +92,7 @@ extern const char kEnable2dCanvasClipAntialiasing[]; CONTENT_EXPORT extern const char kEnableBleedingEdgeRenderingFastPaths[]; CONTENT_EXPORT extern const char kEnableCompositorAnimationTimelines[]; CONTENT_EXPORT extern const char kEnableCredentialManagerAPI[]; +CONTENT_EXPORT extern const char kEnableBeginFrameScheduling[]; CONTENT_EXPORT extern const char kEnablePreferCompositingToLCDText[]; CONTENT_EXPORT extern const char kEnableBlinkFeatures[]; CONTENT_EXPORT extern const char kEnableBrowserSideNavigation[]; diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index 6eb57c9c71f99f..f3f6489daee1f0 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc @@ -233,13 +233,12 @@ void RenderWidgetCompositor::Initialize() { settings.use_compositor_animation_timelines = true; blink::WebRuntimeFeatures::enableCompositorAnimationTimelines(true); } -#if !defined(OS_MACOSX) - if (!widget_->for_oopif()) { + if (cmd->HasSwitch(switches::kEnableBeginFrameScheduling) && + !widget_->for_oopif()) { // TODO(simonhong): Apply BeginFrame scheduling for OOPIF. // See crbug.com/471411. settings.use_external_begin_frame_source = true; } -#endif settings.default_tile_size = CalculateDefaultTileSize(widget_); if (cmd->HasSwitch(switches::kDefaultTileWidth)) { diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn index 9002d5e92ee722..a0944fe78494cb 100644 --- a/ui/compositor/BUILD.gn +++ b/ui/compositor/BUILD.gn @@ -20,6 +20,8 @@ component("compositor") { "compositor_observer.h", "compositor_switches.cc", "compositor_switches.h", + "compositor_vsync_manager.cc", + "compositor_vsync_manager.h", "debug_utils.cc", "debug_utils.h", "dip_util.cc", diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 67a937ef96643b..c50f9efdddb532 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc @@ -27,6 +27,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "ui/compositor/compositor_observer.h" #include "ui/compositor/compositor_switches.h" +#include "ui/compositor/compositor_vsync_manager.h" #include "ui/compositor/dip_util.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animator_collection.h" @@ -72,6 +73,7 @@ Compositor::Compositor(gfx::AcceleratedWidget widget, widget_(widget), surface_id_allocator_(context_factory->CreateSurfaceIdAllocator()), task_runner_(task_runner), + vsync_manager_(new CompositorVSyncManager()), device_scale_factor_(0.0f), last_started_frame_(0), last_ended_frame_(0), @@ -255,9 +257,8 @@ bool Compositor::IsVisible() { return host_->visible(); } -void Compositor::SetAuthoritativeVSyncInterval( - const base::TimeDelta& interval) { - host_->SetAuthoritativeVSyncInterval(interval); +scoped_refptr Compositor::vsync_manager() const { + return vsync_manager_; } void Compositor::AddObserver(CompositorObserver* observer) { diff --git a/ui/compositor/compositor.gyp b/ui/compositor/compositor.gyp index 41950aa3c0cf76..92f5ef4e51117f 100644 --- a/ui/compositor/compositor.gyp +++ b/ui/compositor/compositor.gyp @@ -38,6 +38,8 @@ 'compositor_observer.h', 'compositor_switches.cc', 'compositor_switches.h', + 'compositor_vsync_manager.cc', + 'compositor_vsync_manager.h', 'debug_utils.cc', 'debug_utils.h', 'dip_util.cc', diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index 7965b15e354b69..cf115b0238f064 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h @@ -220,17 +220,12 @@ class COMPOSITOR_EXPORT Compositor // Gets the visibility of the underlying compositor. bool IsVisible(); - // The "authoritative" vsync interval, if provided, will override interval - // reported from 3D context. This is typically the value reported by a more - // reliable source, e.g, the platform display configuration. - // In the particular case of ChromeOS -- this is the value queried through - // XRandR, which is more reliable than the value queried through the 3D - // context. - void SetAuthoritativeVSyncInterval(const base::TimeDelta& interval); - // Returns the widget for this compositor. gfx::AcceleratedWidget widget() const { return widget_; } + // Returns the vsync manager for this compositor. + scoped_refptr vsync_manager() const; + // Returns the main thread task runner this compositor uses. Users of the // compositor generally shouldn't use this. scoped_refptr task_runner() const { @@ -342,6 +337,9 @@ class COMPOSITOR_EXPORT Compositor scoped_ptr host_; scoped_refptr task_runner_; + // The manager of vsync parameters for this compositor. + scoped_refptr vsync_manager_; + // The device scale factor of the monitor that this compositor is compositing // layers on. float device_scale_factor_; diff --git a/ui/compositor/compositor_vsync_manager.cc b/ui/compositor/compositor_vsync_manager.cc new file mode 100644 index 00000000000000..f51847ca7bf2cf --- /dev/null +++ b/ui/compositor/compositor_vsync_manager.cc @@ -0,0 +1,46 @@ +// 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 "ui/compositor/compositor_vsync_manager.h" + +namespace ui { + +CompositorVSyncManager::CompositorVSyncManager() + : authoritative_vsync_interval_(base::TimeDelta::FromSeconds(0)) { +} + +CompositorVSyncManager::~CompositorVSyncManager() {} + +void CompositorVSyncManager::SetAuthoritativeVSyncInterval( + base::TimeDelta interval) { + authoritative_vsync_interval_ = interval; + last_interval_ = interval; + NotifyObservers(last_timebase_, last_interval_); +} + +void CompositorVSyncManager::UpdateVSyncParameters(base::TimeTicks timebase, + base::TimeDelta interval) { + if (authoritative_vsync_interval_ != base::TimeDelta::FromSeconds(0)) + interval = authoritative_vsync_interval_; + last_timebase_ = timebase; + last_interval_ = interval; + NotifyObservers(timebase, interval); +} + +void CompositorVSyncManager::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); + observer->OnUpdateVSyncParameters(last_timebase_, last_interval_); +} + +void CompositorVSyncManager::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); +} + +void CompositorVSyncManager::NotifyObservers(base::TimeTicks timebase, + base::TimeDelta interval) { + FOR_EACH_OBSERVER(CompositorVSyncManager::Observer, observer_list_, + OnUpdateVSyncParameters(timebase, interval)); +} + +} // namespace ui diff --git a/ui/compositor/compositor_vsync_manager.h b/ui/compositor/compositor_vsync_manager.h new file mode 100644 index 00000000000000..7e9e07b862653e --- /dev/null +++ b/ui/compositor/compositor_vsync_manager.h @@ -0,0 +1,65 @@ +// 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 UI_COMPOSITOR_COMPOSITOR_VSYNC_MANAGER_H_ +#define UI_COMPOSITOR_COMPOSITOR_VSYNC_MANAGER_H_ + +#include "base/memory/ref_counted.h" +#include "base/observer_list.h" +#include "base/synchronization/lock.h" +#include "base/time/time.h" +#include "ui/compositor/compositor_export.h" + +namespace ui { + +// This class manages vsync parameters for a compositor. It merges updates of +// the parameters from different sources and sends the merged updates to +// observers which register to it. +class COMPOSITOR_EXPORT CompositorVSyncManager + : public base::RefCounted { + public: + class Observer { + public: + virtual void OnUpdateVSyncParameters(base::TimeTicks timebase, + base::TimeDelta interval) = 0; + }; + + CompositorVSyncManager(); + + // The "authoritative" vsync interval, if provided, will override |interval| + // as reported by UpdateVSyncParameters() whenever it is called. This is + // typically the value reported by a more reliable source, e.g. the platform + // display configuration. In the particular case of ChromeOS -- this is the + // value queried through XRandR, which is more reliable than the value + // queried through the 3D context. + void SetAuthoritativeVSyncInterval(base::TimeDelta interval); + + // The vsync parameters consist of |timebase|, which is the platform timestamp + // of the last vsync, and |interval|, which is the interval between vsyncs. + // |interval| may be overriden by SetAuthoritativeVSyncInterval() above. + void UpdateVSyncParameters(base::TimeTicks timebase, + base::TimeDelta interval); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + private: + friend class base::RefCounted; + + ~CompositorVSyncManager(); + + void NotifyObservers(base::TimeTicks timebase, base::TimeDelta interval); + + ObserverList observer_list_; + + base::TimeTicks last_timebase_; + base::TimeDelta last_interval_; + base::TimeDelta authoritative_vsync_interval_; + + DISALLOW_COPY_AND_ASSIGN(CompositorVSyncManager); +}; + +} // namespace ui + +#endif // UI_COMPOSITOR_COMPOSITOR_VSYNC_MANAGER_H_