From d2fe09074199ff2c36948618355118cbdb058365 Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Tue, 24 Nov 2020 23:47:54 +0000 Subject: [PATCH] Bug 1645528 - Connect nsRefreshDrivers in content processes with a widget-local vsync source r=mattwoodrow,emilio To allow `requestAnimationFrame()` and similar things to run at monitor speed if there is only a window-specific vsyncsource available. This is the case for Wayland and, in the future, EGL/X11. Other backends may opt for window specific vsyncsources as well at some point. The idea is to, instead of using global vsync objects, expose a vsyncsource from nsWindow and use it for refresh drivers. For the content process, move VsyncChild to BrowserChild, so for each Browserchild there is only one VsyncChild to which all refresh drivers connect. IPC in managed either by PBrowser or PBackground. Right now, PBrowser is only used on Wayland, as both PBrowser and the Wayland vsyncsource run on the main thread. Other backends keep using the background thread for now. While at it, make it so that we constantly update the refresh rate. This is necessary for Wayland, but also on other platforms variable refresh rates are increasingly common. When using PVsync, limit updates to once in every 250ms in order to minimize overhead while still updating fast. How to test: - run the Wayland backend - enable `widget.wayland_vsync.enabled` - optionally: disable `privacy.reduceTimerPrecision` - run `vsynctester.com` or `testufo.com` Expected results: Instead of fixed 60Hz, things should update at monitor refresh rate - e.g. 144Hz Original patch by Kenny Levinsen. Differential Revision: https://phabricator.services.mozilla.com/D93173 --- dom/ipc/BrowserChild.cpp | 40 ++++++ dom/ipc/BrowserChild.h | 11 ++ dom/ipc/BrowserParent.cpp | 26 ++++ dom/ipc/BrowserParent.h | 9 ++ dom/ipc/PBrowser.ipdl | 7 + {layout => dom}/ipc/PVsync.ipdl | 14 +- {layout => dom}/ipc/VsyncChild.cpp | 61 ++++++--- {layout => dom}/ipc/VsyncChild.h | 45 ++----- {layout => dom}/ipc/VsyncParent.cpp | 76 +++++------ {layout => dom}/ipc/VsyncParent.h | 36 +++-- dom/ipc/moz.build | 5 + ipc/glue/BackgroundChildImpl.cpp | 12 +- ipc/glue/BackgroundParentImpl.cpp | 10 +- ipc/glue/BackgroundParentImpl.h | 5 - layout/base/nsPresContext.cpp | 3 - layout/base/nsRefreshDriver.cpp | 201 ++++++++-------------------- layout/base/nsRefreshDriver.h | 12 -- layout/base/nsRefreshObservers.h | 3 - layout/ipc/moz.build | 11 -- 19 files changed, 282 insertions(+), 305 deletions(-) rename {layout => dom}/ipc/PVsync.ipdl (78%) rename {layout => dom}/ipc/VsyncChild.cpp (57%) rename {layout => dom}/ipc/VsyncChild.h (51%) rename {layout => dom}/ipc/VsyncParent.cpp (60%) rename {layout => dom}/ipc/VsyncParent.h (70%) diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp index 38128882d7a8..62399427e484 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp @@ -14,6 +14,7 @@ #include #include +#include "BackgroundChild.h" #include "BrowserParent.h" #include "ClientLayerManager.h" #include "ContentChild.h" @@ -74,6 +75,7 @@ #include "mozilla/gfx/Matrix.h" #include "mozilla/gfx/gfxVars.h" #include "mozilla/ipc/BackgroundUtils.h" +#include "mozilla/ipc/PBackgroundChild.h" #include "mozilla/ipc/URIUtils.h" #include "mozilla/layers/APZCCallbackHelper.h" #include "mozilla/layers/APZCTreeManagerChild.h" @@ -142,6 +144,10 @@ # include "mozilla/plugins/PluginWidgetChild.h" #endif +#ifdef MOZ_WAYLAND +# include "nsAppRunner.h" +#endif + #ifdef NS_PRINTING # include "nsIPrintSession.h" # include "nsIPrintSettings.h" @@ -314,6 +320,7 @@ BrowserChild::BrowserChild(ContentChild* aManager, const TabId& aTabId, mDidFakeShow(false), mTriedBrowserInit(false), mOrientation(hal::eScreenOrientation_PortraitPrimary), + mVsyncChild(nullptr), mIgnoreKeyPressEvent(false), mHasValidInnerSize(false), mDestroyed(false), @@ -550,6 +557,8 @@ nsresult BrowserChild::Init(mozIDOMWindowProxy* aParent, NS_ENSURE_SUCCESS(rv, rv); #endif + InitVsyncChild(); + // We've all set up, make sure our visibility state is consistent. This is // important for OOP iframes, which start off as hidden. UpdateVisibility(); @@ -557,6 +566,20 @@ nsresult BrowserChild::Init(mozIDOMWindowProxy* aParent, return NS_OK; } +void BrowserChild::InitVsyncChild() { +#if defined(MOZ_WAYLAND) + if (!IsWaylandDisabled()) { + PVsyncChild* actor = SendPVsyncConstructor(); + mVsyncChild = static_cast(actor); + } else +#endif + { + PBackgroundChild* actorChild = + BackgroundChild::GetOrCreateForCurrentThread(); + mVsyncChild = static_cast(actorChild->SendPVsyncConstructor()); + } +} + void BrowserChild::NotifyTabContextUpdated() { nsCOMPtr docShell = do_GetInterface(WebNavigation()); MOZ_ASSERT(docShell); @@ -2143,6 +2166,23 @@ bool BrowserChild::DeallocPFilePickerChild(PFilePickerChild* actor) { return true; } +PVsyncChild* BrowserChild::AllocPVsyncChild() { + RefPtr actor = new VsyncChild(); + // There still has one ref-count after return, and it will be released in + // DeallocPVsyncChild(). + return actor.forget().take(); +} + +bool BrowserChild::DeallocPVsyncChild(PVsyncChild* aActor) { + MOZ_ASSERT(aActor); + + // This actor already has one ref-count. Please check AllocPVsyncChild(). + RefPtr actor = dont_AddRef(static_cast(aActor)); + return true; +} + +RefPtr BrowserChild::GetVsyncChild() { return mVsyncChild; } + mozilla::ipc::IPCResult BrowserChild::RecvActivateFrameEvent( const nsString& aType, const bool& capture) { nsCOMPtr window = do_GetInterface(WebNavigation()); diff --git a/dom/ipc/BrowserChild.h b/dom/ipc/BrowserChild.h index f93c71fc2107..03dfe3163aff 100644 --- a/dom/ipc/BrowserChild.h +++ b/dom/ipc/BrowserChild.h @@ -29,6 +29,7 @@ #include "mozilla/dom/CoalescedMouseData.h" #include "mozilla/dom/CoalescedWheelData.h" #include "mozilla/dom/MessageManagerCallback.h" +#include "mozilla/dom/VsyncChild.h" #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/EventDispatcher.h" #include "mozilla/EventForwards.h" @@ -436,6 +437,12 @@ class BrowserChild final : public nsMessageManagerScriptExecutor, PFilePickerChild* AllocPFilePickerChild(const nsString& aTitle, const int16_t& aMode); + virtual PVsyncChild* AllocPVsyncChild(); + + virtual bool DeallocPVsyncChild(PVsyncChild* aActor); + + RefPtr GetVsyncChild(); + bool DeallocPFilePickerChild(PFilePickerChild* aActor); nsIWebNavigation* WebNavigation() const { return mWebNav; } @@ -747,6 +754,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor, const mozilla::layers::CompositorOptions& aCompositorOptions); void InitAPZState(); + void InitVsyncChild(); + void DestroyWindow(); void ApplyParentShowInfo(const ParentShowInfo&); @@ -814,6 +823,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor, bool mTriedBrowserInit; hal::ScreenOrientation mOrientation; + RefPtr mVsyncChild; + bool mIgnoreKeyPressEvent; RefPtr mAPZEventState; SetAllowedTouchBehaviorCallback mSetAllowedTouchBehaviorCallback; diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp index 2f73893bb92a..72eb763e8c3a 100644 --- a/dom/ipc/BrowserParent.cpp +++ b/dom/ipc/BrowserParent.cpp @@ -129,6 +129,7 @@ #include "mozilla/dom/CrashReport.h" #include "nsISecureBrowserUI.h" #include "nsIXULRuntime.h" +#include "VsyncSource.h" #ifdef XP_WIN # include "mozilla/plugins/PluginWidgetParent.h" @@ -224,6 +225,7 @@ BrowserParent::BrowserParent(ContentParent* aManager, const TabId& aTabId, mCustomCursorHotspotX(0), mCustomCursorHotspotY(0), mVerifyDropLinks{}, + mVsyncParent(nullptr), mDocShellIsActive(false), mMarkedDestroying(false), mIsDestroyed(false), @@ -563,6 +565,8 @@ void BrowserParent::SetOwnerElement(Element* aElement) { mBrowsingContext->SetEmbedderElement(mFrameElement); } + UpdateVsyncParentVsyncSource(); + VisitChildren([aElement](BrowserBridgeParent* aBrowser) { if (auto* browserParent = aBrowser->GetBrowserParent()) { browserParent->SetOwnerElement(aElement); @@ -1346,6 +1350,28 @@ IPCResult BrowserParent::RecvNewWindowGlobal( return IPC_OK(); } +PVsyncParent* BrowserParent::AllocPVsyncParent() { + MOZ_ASSERT(!mVsyncParent); + mVsyncParent = new VsyncParent(); + UpdateVsyncParentVsyncSource(); + return mVsyncParent.get(); +} + +bool BrowserParent::DeallocPVsyncParent(PVsyncParent* aActor) { + mVsyncParent = nullptr; + return true; +} + +void BrowserParent::UpdateVsyncParentVsyncSource() { + if (!mVsyncParent) { + return; + } + + if (nsCOMPtr widget = GetWidget()) { + mVsyncParent->UpdateVsyncSource(widget->GetVsyncSource()); + } +} + void BrowserParent::SendMouseEvent(const nsAString& aType, float aX, float aY, int32_t aButton, int32_t aClickCount, int32_t aModifiers) { diff --git a/dom/ipc/BrowserParent.h b/dom/ipc/BrowserParent.h index f4161f3dbe09..549daaef72aa 100644 --- a/dom/ipc/BrowserParent.h +++ b/dom/ipc/BrowserParent.h @@ -18,6 +18,7 @@ #include "mozilla/dom/BrowserBridgeParent.h" #include "mozilla/dom/PBrowserParent.h" #include "mozilla/dom/TabContext.h" +#include "mozilla/dom/VsyncParent.h" #include "mozilla/dom/ipc/IdType.h" #include "mozilla/layout/RemoteLayerTreeOwner.h" #include "nsCOMPtr.h" @@ -460,6 +461,10 @@ class BrowserParent final : public PBrowserParent, bool DeallocPColorPickerParent(PColorPickerParent* aColorPicker); + PVsyncParent* AllocPVsyncParent(); + + bool DeallocPVsyncParent(PVsyncParent* aActor); + #ifdef ACCESSIBILITY PDocAccessibleParent* AllocPDocAccessibleParent(PDocAccessibleParent*, const uint64_t&, @@ -872,6 +877,8 @@ class BrowserParent final : public PBrowserParent, void SendRealTouchMoveEvent(WidgetTouchEvent& aEvent, APZData& aAPZData, uint32_t aConsecutiveTouchMoveCount); + void UpdateVsyncParentVsyncSource(); + public: // Unsets sTopLevelWebFocus regardless of its current value. static void UnsetTopLevelWebFocusAll(); @@ -957,6 +964,8 @@ class BrowserParent final : public PBrowserParent, nsTArray mVerifyDropLinks; + RefPtr mVsyncParent; + #ifdef DEBUG int32_t mActiveSupressDisplayportCount = 0; #endif diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 98091cde41c2..1628f1a58e6b 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -20,6 +20,7 @@ include protocol PRemoteLazyInputStream; include protocol PPaymentRequest; include protocol PWindowGlobal; include protocol PBrowserBridge; +include protocol PVsync; include DOMTypes; include NeckoChannelParams; @@ -190,6 +191,7 @@ nested(upto inside_cpow) sync refcounted protocol PBrowser manages PPaymentRequest; manages PWindowGlobal; manages PBrowserBridge; + manages PVsync; both: async AsyncMessage(nsString aMessage, ClonedMessageData aData); @@ -217,6 +219,11 @@ parent: async PPaymentRequest(); + /** + * Create a new Vsync connection for our associated root widget + */ + async PVsync(); + /** * Sends an NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW to be adopted by the * widget's shareable window on the chrome side. Only used on Windows. diff --git a/layout/ipc/PVsync.ipdl b/dom/ipc/PVsync.ipdl similarity index 78% rename from layout/ipc/PVsync.ipdl rename to dom/ipc/PVsync.ipdl index 6cca91cb4bc1..216171633dc2 100644 --- a/layout/ipc/PVsync.ipdl +++ b/dom/ipc/PVsync.ipdl @@ -4,22 +4,23 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ include protocol PBackground; +include protocol PBrowser; include "mozilla/layers/LayersMessageUtils.h"; using class mozilla::TimeStamp from "mozilla/TimeStamp.h"; using mozilla::VsyncEvent from "mozilla/VsyncDispatcher.h"; namespace mozilla { -namespace layout { +namespace dom { /* - * The PVsync is a sub-protocol in PBackground and it is used to notify - * the vsync event from chrome to content process. It also provides the + * The PVsync is a sub-protocol in PBackground or PBrowser and it is used to + * notify the vsync event from chrome to content process. It also provides the * interfaces for content to observe/unobserve vsync event notifications. */ async protocol PVsync { - manager PBackground; + manager PBackground or PBrowser; child: // Send vsync event from chrome to content process. @@ -35,10 +36,9 @@ parent: async RequestVsyncRate(); // This message is never sent. Each PVsync actor will stay alive as long as - // its PBackground manager. + // its PBackground or PBrowser manager. async __delete__(); }; -} // namespace layout +} // namespace dom } // namespace mozilla - diff --git a/layout/ipc/VsyncChild.cpp b/dom/ipc/VsyncChild.cpp similarity index 57% rename from layout/ipc/VsyncChild.cpp rename to dom/ipc/VsyncChild.cpp index 1d358fe8e677..965aeec2ffb2 100644 --- a/layout/ipc/VsyncChild.cpp +++ b/dom/ipc/VsyncChild.cpp @@ -10,17 +10,18 @@ #include "mozilla/VsyncDispatcher.h" #include "nsThreadUtils.h" -namespace mozilla::layout { +namespace mozilla::dom { VsyncChild::VsyncChild() - : mObservingVsync(false), - mIsShutdown(false), - mVsyncRate(TimeDuration::Forever()) { + : mIsShutdown(false), + mVsyncRate(TimeDuration::Forever()), + lastVsyncRateTime(TimeStamp()) { MOZ_ASSERT(NS_IsMainThread()); } VsyncChild::~VsyncChild() { MOZ_ASSERT(NS_IsMainThread()); } +/* do not delete yet so the file history is preserved bool VsyncChild::SendObserve() { MOZ_ASSERT(NS_IsMainThread()); if (!mObservingVsync && !mIsShutdown) { @@ -38,12 +39,42 @@ bool VsyncChild::SendUnobserve() { } return true; } +*/ + +void VsyncChild::AddChildRefreshTimer(VsyncObserver* aVsyncObserver) { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!mObservers.Contains(aVsyncObserver)); + + if (mIsShutdown) { + return; + } + + if (mObservers.IsEmpty()) { + Unused << PVsyncChild::SendObserve(); + } + mObservers.AppendElement(std::move(aVsyncObserver)); +} + +void VsyncChild::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver) { + MOZ_ASSERT(NS_IsMainThread()); + if (mIsShutdown) { + return; + } + + if (mObservers.RemoveElement(aVsyncObserver) && mObservers.IsEmpty()) { + Unused << PVsyncChild::SendUnobserve(); + } +} void VsyncChild::ActorDestroy(ActorDestroyReason aActorDestroyReason) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mIsShutdown); mIsShutdown = true; - mObserver = nullptr; + + if (!mObservers.IsEmpty()) { + Unused << PVsyncChild::SendUnobserve(); + } + mObservers.Clear(); } mozilla::ipc::IPCResult VsyncChild::RecvNotify(const VsyncEvent& aVsync) { @@ -51,30 +82,26 @@ mozilla::ipc::IPCResult VsyncChild::RecvNotify(const VsyncEvent& aVsync) { MOZ_ASSERT(!mIsShutdown); SchedulerGroup::MarkVsyncRan(); - if (mObservingVsync && mObserver) { - mObserver->NotifyVsync(aVsync); + + for (VsyncObserver* observer : mObservers.ForwardRange()) { + observer->NotifyVsync(aVsync); } return IPC_OK(); } -void VsyncChild::SetVsyncObserver(VsyncObserver* aVsyncObserver) { - MOZ_ASSERT(NS_IsMainThread()); - mObserver = aVsyncObserver; -} - TimeDuration VsyncChild::GetVsyncRate() { - if (mVsyncRate == TimeDuration::Forever()) { + // Throttle vsync rate requests to avoid unnecessary IPC + if (lastVsyncRateTime.IsNull() || + (TimeStamp::Now() - lastVsyncRateTime).ToMilliseconds() > 250) { PVsyncChild::SendRequestVsyncRate(); + lastVsyncRateTime = TimeStamp::Now(); } - return mVsyncRate; } -TimeDuration VsyncChild::VsyncRate() { return mVsyncRate; } - mozilla::ipc::IPCResult VsyncChild::RecvVsyncRate(const float& aVsyncRate) { mVsyncRate = TimeDuration::FromMilliseconds(aVsyncRate); return IPC_OK(); } -} // namespace mozilla::layout +} // namespace mozilla::dom diff --git a/layout/ipc/VsyncChild.h b/dom/ipc/VsyncChild.h similarity index 51% rename from layout/ipc/VsyncChild.h rename to dom/ipc/VsyncChild.h index 23c915f3358f..966e8d3c003e 100644 --- a/layout/ipc/VsyncChild.h +++ b/dom/ipc/VsyncChild.h @@ -4,22 +4,19 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef mozilla_layout_ipc_VsyncChild_h -#define mozilla_layout_ipc_VsyncChild_h +#ifndef mozilla_dom_ipc_VsyncChild_h +#define mozilla_dom_ipc_VsyncChild_h -#include "mozilla/layout/PVsyncChild.h" -#include "nsISupportsImpl.h" +#include "mozilla/dom/PVsyncChild.h" #include "mozilla/RefPtr.h" +#include "nsISupportsImpl.h" +#include "nsTObserverArray.h" namespace mozilla { class VsyncObserver; -namespace ipc { -class BackgroundChildImpl; -} // namespace ipc - -namespace layout { +namespace dom { // The PVsyncChild actor receives a vsync event from the main process and // delivers it to the child process. Currently this is restricted to the main @@ -28,44 +25,30 @@ namespace layout { class VsyncChild final : public PVsyncChild { NS_INLINE_DECL_REFCOUNTING(VsyncChild) - friend class mozilla::ipc::BackgroundChildImpl; friend class PVsyncChild; public: - // Hide the SendObserve/SendUnobserve in PVsyncChild. We add an flag - // mObservingVsync to handle the race problem of unobserving vsync event. - bool SendObserve(); - bool SendUnobserve(); + VsyncChild(); + + void AddChildRefreshTimer(VsyncObserver* aVsyncObserver); + void RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver); - // Bind a VsyncObserver into VsyncChild after ipc channel connected. - void SetVsyncObserver(VsyncObserver* aVsyncObserver); - // GetVsyncRate is a getter for mVsyncRate which sends a requests to - // VsyncParent to retreive the hardware vsync rate if mVsyncRate - // hasn't already been set. TimeDuration GetVsyncRate(); - // VsyncRate is a getter for mVsyncRate which always returns - // mVsyncRate directly, potentially returning - // TimeDuration::Forever() if mVsyncRate hasn't been set by calling - // GetVsyncRate. - TimeDuration VsyncRate(); private: - VsyncChild(); virtual ~VsyncChild(); mozilla::ipc::IPCResult RecvNotify(const VsyncEvent& aVsync); mozilla::ipc::IPCResult RecvVsyncRate(const float& aVsyncRate); virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override; - bool mObservingVsync; bool mIsShutdown; - - // The content side vsync observer. - RefPtr mObserver; TimeDuration mVsyncRate; + TimeStamp lastVsyncRateTime; + nsTObserverArray mObservers; }; -} // namespace layout +} // namespace dom } // namespace mozilla -#endif // mozilla_layout_ipc_VsyncChild_h +#endif // mozilla_dom_ipc_VsyncChild_h diff --git a/layout/ipc/VsyncParent.cpp b/dom/ipc/VsyncParent.cpp similarity index 60% rename from layout/ipc/VsyncParent.cpp rename to dom/ipc/VsyncParent.cpp index c039af999b39..877b23655073 100644 --- a/layout/ipc/VsyncParent.cpp +++ b/dom/ipc/VsyncParent.cpp @@ -10,51 +10,49 @@ #include "BackgroundParentImpl.h" #include "gfxPlatform.h" #include "mozilla/Unused.h" +#include "nsIThread.h" #include "nsThreadUtils.h" #include "VsyncSource.h" -namespace mozilla { - -using namespace ipc; - -namespace layout { - -/*static*/ -already_AddRefed VsyncParent::Create() { - AssertIsOnBackgroundThread(); - RefPtr vsyncSource = - gfxPlatform::GetPlatform()->GetHardwareVsync(); - RefPtr vsyncParent = new VsyncParent(); - vsyncParent->mVsyncDispatcher = vsyncSource->GetRefreshTimerVsyncDispatcher(); - return vsyncParent.forget(); -} +namespace mozilla::dom { VsyncParent::VsyncParent() : mObservingVsync(false), mDestroyed(false), - mBackgroundThread(NS_GetCurrentThread()) { - MOZ_ASSERT(mBackgroundThread); - AssertIsOnBackgroundThread(); -} + mInitialThread(NS_GetCurrentThread()) {} -VsyncParent::~VsyncParent() { - // Since we use NS_INLINE_DECL_THREADSAFE_REFCOUNTING, we can't make sure - // VsyncParent is always released on the background thread. +void VsyncParent::UpdateVsyncSource( + const RefPtr& aVsyncSource) { + mVsyncSource = aVsyncSource; + if (!mVsyncSource) { + mVsyncSource = gfxPlatform::GetPlatform()->GetHardwareVsync(); + } + + if (mObservingVsync) { + mVsyncDispatcher->RemoveChildRefreshTimer(this); + } + mVsyncDispatcher = mVsyncSource->GetRefreshTimerVsyncDispatcher(); + if (mObservingVsync) { + mVsyncDispatcher->AddChildRefreshTimer(this); + } } bool VsyncParent::NotifyVsync(const VsyncEvent& aVsync) { + if (IsOnInitialThread()) { + DispatchVsyncEvent(aVsync); + return true; + } + // Called on hardware vsync thread. We should post to current ipc thread. - MOZ_ASSERT(!IsOnBackgroundThread()); nsCOMPtr vsyncEvent = NewRunnableMethod( - "layout::VsyncParent::DispatchVsyncEvent", this, + "dom::VsyncParent::DispatchVsyncEvent", this, &VsyncParent::DispatchVsyncEvent, aVsync); - MOZ_ALWAYS_SUCCEEDS( - mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL)); + MOZ_ALWAYS_SUCCEEDS(mInitialThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL)); return true; } void VsyncParent::DispatchVsyncEvent(const VsyncEvent& aVsync) { - AssertIsOnBackgroundThread(); + AssertIsOnInitialThread(); // If we call NotifyVsync() when we handle ActorDestroy() message, we might // still call DispatchVsyncEvent(). @@ -67,17 +65,14 @@ void VsyncParent::DispatchVsyncEvent(const VsyncEvent& aVsync) { } mozilla::ipc::IPCResult VsyncParent::RecvRequestVsyncRate() { - AssertIsOnBackgroundThread(); - TimeDuration vsyncRate = gfxPlatform::GetPlatform() - ->GetHardwareVsync() - ->GetGlobalDisplay() - .GetVsyncRate(); + AssertIsOnInitialThread(); + TimeDuration vsyncRate = mVsyncSource->GetGlobalDisplay().GetVsyncRate(); Unused << SendVsyncRate(vsyncRate.ToMilliseconds()); return IPC_OK(); } mozilla::ipc::IPCResult VsyncParent::RecvObserve() { - AssertIsOnBackgroundThread(); + AssertIsOnInitialThread(); if (!mObservingVsync) { mVsyncDispatcher->AddChildRefreshTimer(this); mObservingVsync = true; @@ -87,7 +82,7 @@ mozilla::ipc::IPCResult VsyncParent::RecvObserve() { } mozilla::ipc::IPCResult VsyncParent::RecvUnobserve() { - AssertIsOnBackgroundThread(); + AssertIsOnInitialThread(); if (mObservingVsync) { mVsyncDispatcher->RemoveChildRefreshTimer(this); mObservingVsync = false; @@ -96,9 +91,9 @@ mozilla::ipc::IPCResult VsyncParent::RecvUnobserve() { return IPC_FAIL_NO_REASON(this); } -void VsyncParent::ActorDestroy(ActorDestroyReason aReason) { +void VsyncParent::ActorDestroy(ActorDestroyReason aActorDestroyReason) { MOZ_ASSERT(!mDestroyed); - AssertIsOnBackgroundThread(); + AssertIsOnInitialThread(); if (mObservingVsync) { mVsyncDispatcher->RemoveChildRefreshTimer(this); } @@ -106,5 +101,10 @@ void VsyncParent::ActorDestroy(ActorDestroyReason aReason) { mDestroyed = true; } -} // namespace layout -} // namespace mozilla +bool VsyncParent::IsOnInitialThread() { + return NS_GetCurrentThread() == mInitialThread; +} + +void VsyncParent::AssertIsOnInitialThread() { MOZ_ASSERT(IsOnInitialThread()); } + +} // namespace mozilla::dom diff --git a/layout/ipc/VsyncParent.h b/dom/ipc/VsyncParent.h similarity index 70% rename from layout/ipc/VsyncParent.h rename to dom/ipc/VsyncParent.h index 2d0885d81a7a..a3ba1999a141 100644 --- a/layout/ipc/VsyncParent.h +++ b/dom/ipc/VsyncParent.h @@ -4,36 +4,31 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef mozilla_layout_ipc_VsyncParent_h -#define mozilla_layout_ipc_VsyncParent_h +#ifndef mozilla_dom_ipc_VsyncParent_h +#define mozilla_dom_ipc_VsyncParent_h -#include "mozilla/layout/PVsyncParent.h" +#include "mozilla/dom/PVsyncParent.h" #include "mozilla/VsyncDispatcher.h" #include "nsCOMPtr.h" #include "mozilla/RefPtr.h" +#include "VsyncSource.h" class nsIThread; -namespace mozilla { - -namespace ipc { -class BackgroundParentImpl; -} // namespace ipc - -namespace layout { +namespace mozilla::dom { // Use PBackground thread in the main process to send vsync notifications to // content process. This actor will be released when its parent protocol calls // DeallocPVsyncParent(). class VsyncParent final : public PVsyncParent, public VsyncObserver { - friend class mozilla::ipc::BackgroundParentImpl; friend class PVsyncParent; - private: - static already_AddRefed Create(); - + public: VsyncParent(); - virtual ~VsyncParent(); + void UpdateVsyncSource(const RefPtr& aVsyncSource); + + private: + virtual ~VsyncParent() = default; virtual bool NotifyVsync(const VsyncEvent& aVsync) override; mozilla::ipc::IPCResult RecvRequestVsyncRate(); @@ -44,13 +39,16 @@ class VsyncParent final : public PVsyncParent, public VsyncObserver { void DispatchVsyncEvent(const VsyncEvent& aVsync); + bool IsOnInitialThread(); + void AssertIsOnInitialThread(); + bool mObservingVsync; bool mDestroyed; - nsCOMPtr mBackgroundThread; + nsCOMPtr mInitialThread; + RefPtr mVsyncSource; RefPtr mVsyncDispatcher; }; -} // namespace layout -} // namespace mozilla +} // namespace mozilla::dom -#endif // mozilla_layout_ipc_VsyncParent_h +#endif // mozilla_dom_ipc_VsyncParent_h diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index 57d289b658ee..caa1bfc88eb5 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -71,6 +71,8 @@ EXPORTS.mozilla.dom += [ "URLClassifierChild.h", "URLClassifierParent.h", "UserActivationIPCUtils.h", + "VsyncChild.h", + "VsyncParent.h", "WindowGlobalActor.h", "WindowGlobalChild.h", "WindowGlobalParent.h", @@ -130,6 +132,8 @@ UNIFIED_SOURCES += [ SOURCES += [ "ContentChild.cpp", "ProcessHangMonitor.cpp", + "VsyncChild.cpp", + "VsyncParent.cpp", ] PREPROCESSED_IPDL_SOURCES += [ @@ -155,6 +159,7 @@ IPDL_SOURCES += [ "PURLClassifier.ipdl", "PURLClassifierInfo.ipdlh", "PURLClassifierLocal.ipdl", + "PVsync.ipdl", "PWindowGlobal.ipdl", "ServiceWorkerConfiguration.ipdlh", "WindowGlobalTypes.ipdlh", diff --git a/ipc/glue/BackgroundChildImpl.cpp b/ipc/glue/BackgroundChildImpl.cpp index deffc0aa168a..e10c90b5300e 100644 --- a/ipc/glue/BackgroundChildImpl.cpp +++ b/ipc/glue/BackgroundChildImpl.cpp @@ -46,11 +46,11 @@ #include "mozilla/dom/ServiceWorkerContainerChild.h" #include "mozilla/dom/ServiceWorkerManagerChild.h" #include "mozilla/dom/BrowserChild.h" +#include "mozilla/dom/VsyncChild.h" #include "mozilla/ipc/IPCStreamAlloc.h" #include "mozilla/ipc/PBackgroundTestChild.h" #include "mozilla/ipc/PChildToParentStreamChild.h" #include "mozilla/ipc/PParentToChildStreamChild.h" -#include "mozilla/layout/VsyncChild.h" #include "mozilla/net/HttpBackgroundChannelChild.h" #include "mozilla/net/PUDPSocketChild.h" #include "mozilla/dom/network/UDPSocketChild.h" @@ -408,8 +408,8 @@ bool BackgroundChildImpl::DeallocPFileDescriptorSetChild( return true; } -BackgroundChildImpl::PVsyncChild* BackgroundChildImpl::AllocPVsyncChild() { - RefPtr actor = new mozilla::layout::VsyncChild(); +dom::PVsyncChild* BackgroundChildImpl::AllocPVsyncChild() { + RefPtr actor = new dom::VsyncChild(); // There still has one ref-count after return, and it will be released in // DeallocPVsyncChild(). return actor.forget().take(); @@ -419,8 +419,8 @@ bool BackgroundChildImpl::DeallocPVsyncChild(PVsyncChild* aActor) { MOZ_ASSERT(aActor); // This actor already has one ref-count. Please check AllocPVsyncChild(). - RefPtr actor = - dont_AddRef(static_cast(aActor)); + RefPtr actor = + dont_AddRef(static_cast(aActor)); return true; } @@ -619,7 +619,7 @@ bool BackgroundChildImpl::DeallocPClientManagerChild( #ifdef EARLY_BETA_OR_EARLIER void BackgroundChildImpl::OnChannelReceivedMessage(const Message& aMsg) { - if (aMsg.type() == layout::PVsync::MessageType::Msg_Notify__ID) { + if (aMsg.type() == dom::PVsync::MessageType::Msg_Notify__ID) { // Not really necessary to look at the message payload, it will be // <0.5ms away from TimeStamp::Now() SchedulerGroup::MarkVsyncReceived(); diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp index b866b2c457cc..17f08a349c06 100644 --- a/ipc/glue/BackgroundParentImpl.cpp +++ b/ipc/glue/BackgroundParentImpl.cpp @@ -55,6 +55,7 @@ #include "mozilla/dom/network/UDPSocketParent.h" #include "mozilla/dom/quota/ActorsParent.h" #include "mozilla/dom/simpledb/ActorsParent.h" +#include "mozilla/dom/VsyncParent.h" #include "mozilla/ipc/BackgroundParent.h" #include "mozilla/ipc/BackgroundUtils.h" #include "mozilla/ipc/Endpoint.h" @@ -64,7 +65,6 @@ #include "mozilla/ipc/PBackgroundTestParent.h" #include "mozilla/ipc/PChildToParentStreamParent.h" #include "mozilla/ipc/PParentToChildStreamParent.h" -#include "mozilla/layout/VsyncParent.h" #include "mozilla/media/MediaParent.h" #include "mozilla/net/BackgroundDataBridgeParent.h" #include "mozilla/net/HttpBackgroundChannelParent.h" @@ -717,8 +717,8 @@ BackgroundParentImpl::PVsyncParent* BackgroundParentImpl::AllocPVsyncParent() { AssertIsInMainOrSocketProcess(); AssertIsOnBackgroundThread(); - RefPtr actor = - mozilla::layout::VsyncParent::Create(); + RefPtr actor = new mozilla::dom::VsyncParent(); + actor->UpdateVsyncSource(nullptr); // There still has one ref-count after return, and it will be released in // DeallocPVsyncParent(). return actor.forget().take(); @@ -730,8 +730,8 @@ bool BackgroundParentImpl::DeallocPVsyncParent(PVsyncParent* aActor) { MOZ_ASSERT(aActor); // This actor already has one ref-count. Please check AllocPVsyncParent(). - RefPtr actor = - dont_AddRef(static_cast(aActor)); + RefPtr actor = + dont_AddRef(static_cast(aActor)); return true; } diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h index 70a836553c3a..9c169ba81b8b 100644 --- a/ipc/glue/BackgroundParentImpl.h +++ b/ipc/glue/BackgroundParentImpl.h @@ -12,11 +12,6 @@ #include "mozilla/ipc/PBackgroundParent.h" namespace mozilla { - -namespace layout { -class VsyncParent; -} // namespace layout - namespace ipc { // Instances of this class should never be created directly. This class is meant diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index d3a27b70c82c..a2a677af96f7 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -692,9 +692,6 @@ nsresult nsPresContext::Init(nsDeviceContext* aDeviceContext) { if (!mRefreshDriver) { mRefreshDriver = new nsRefreshDriver(this); - if (XRE_IsContentProcess()) { - mRefreshDriver->InitializeTimer(); - } } } diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 461e431d0032..2aa56b2271e1 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -59,10 +59,12 @@ #include "nsViewManager.h" #include "GeckoProfiler.h" #include "nsNPAPIPluginInstance.h" +#include "mozilla/dom/BrowserChild.h" #include "mozilla/dom/CallbackDebuggerNotification.h" #include "mozilla/dom/Event.h" #include "mozilla/dom/Performance.h" #include "mozilla/dom/Selection.h" +#include "mozilla/dom/VsyncChild.h" #include "mozilla/dom/WindowBinding.h" #include "mozilla/RestyleManager.h" #include "Layers.h" @@ -75,7 +77,6 @@ #include "BackgroundChild.h" #include "mozilla/ipc/PBackgroundChild.h" -#include "mozilla/layout/VsyncChild.h" #include "VsyncSource.h" #include "mozilla/VsyncDispatcher.h" #include "mozilla/Unused.h" @@ -246,26 +247,6 @@ class RefreshDriverTimer { TimeStamp MostRecentRefresh() const { return mLastFireTime; } - void SwapRefreshDrivers(RefreshDriverTimer* aNewTimer) { - MOZ_ASSERT(NS_IsMainThread()); - - for (nsRefreshDriver* driver : mContentRefreshDrivers) { - aNewTimer->AddRefreshDriver(driver); - driver->mActiveTimer = aNewTimer; - } - mContentRefreshDrivers.Clear(); - - for (nsRefreshDriver* driver : mRootRefreshDrivers) { - aNewTimer->AddRefreshDriver(driver); - driver->mActiveTimer = aNewTimer; - } - mRootRefreshDrivers.Clear(); - - aNewTimer->mLastFireTime = mLastFireTime; - - StopTimer(); - } - virtual TimeDuration GetTimerRate() = 0; TimeStamp GetIdleDeadlineHint(TimeStamp aDefault) { @@ -446,56 +427,45 @@ class SimpleTimerBasedRefreshDriverTimer : public RefreshDriverTimer { */ class VsyncRefreshDriverTimer : public RefreshDriverTimer { public: - VsyncRefreshDriverTimer() : mVsyncChild(nullptr) { + VsyncRefreshDriverTimer() + : mVsyncChild(nullptr), mVsyncRate(TimeDuration::Forever()) { MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(NS_IsMainThread()); + mVsyncSource = gfxPlatform::GetPlatform()->GetHardwareVsync(); mVsyncObserver = new RefreshDriverVsyncObserver(this); - RefPtr vsyncSource = - gfxPlatform::GetPlatform()->GetHardwareVsync(); MOZ_ALWAYS_TRUE(mVsyncDispatcher = - vsyncSource->GetRefreshTimerVsyncDispatcher()); - mVsyncDispatcher->AddChildRefreshTimer(mVsyncObserver); - mVsyncRate = vsyncSource->GetGlobalDisplay().GetVsyncRate(); - } - - explicit VsyncRefreshDriverTimer(VsyncChild* aVsyncChild) - : mVsyncChild(aVsyncChild) { - MOZ_ASSERT(!XRE_IsParentProcess()); - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mVsyncChild); - mVsyncObserver = new RefreshDriverVsyncObserver(this); - mVsyncChild->SetVsyncObserver(mVsyncObserver); - mVsyncRate = mVsyncChild->GetVsyncRate(); + mVsyncSource->GetRefreshTimerVsyncDispatcher()); } // Constructor for when we have a local vsync source. As it is local, we do // not have to worry about it being re-inited by gfxPlatform on frame rate // change on the global source. explicit VsyncRefreshDriverTimer(const RefPtr& aVsyncSource) - : mVsyncChild(nullptr) { + : mVsyncSource(aVsyncSource), + mVsyncChild(nullptr), + mVsyncRate(TimeDuration::Forever()) { MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(NS_IsMainThread()); - mVsyncSource = aVsyncSource; mVsyncObserver = new RefreshDriverVsyncObserver(this); MOZ_ALWAYS_TRUE(mVsyncDispatcher = aVsyncSource->GetRefreshTimerVsyncDispatcher()); - mVsyncDispatcher->AddChildRefreshTimer(mVsyncObserver); - mVsyncRate = aVsyncSource->GetGlobalDisplay().GetVsyncRate(); + } + + explicit VsyncRefreshDriverTimer(const RefPtr& aVsyncChild) + : mVsyncSource(nullptr), + mVsyncDispatcher(nullptr), + mVsyncChild(aVsyncChild), + mVsyncRate(TimeDuration::Forever()) { + MOZ_ASSERT(XRE_IsContentProcess()); + MOZ_ASSERT(NS_IsMainThread()); + mVsyncObserver = new RefreshDriverVsyncObserver(this); } TimeDuration GetTimerRate() override { - if (mVsyncRate != TimeDuration::Forever()) { - return mVsyncRate; - } - - if (mVsyncChild) { - // VsyncChild::VsyncRate() is a simple getter for the cached - // hardware vsync rate. We depend on that - // VsyncChild::GetVsyncRate() being called in the constructor - // will result in a response with the actual vsync rate sooner - // or later. Until that happens VsyncChild::VsyncRate() returns - // TimeDuration::Forever() and we have to guess below. - mVsyncRate = mVsyncChild->VsyncRate(); + if (mVsyncSource) { + mVsyncRate = mVsyncSource->GetGlobalDisplay().GetVsyncRate(); + } else if (mVsyncChild) { + mVsyncRate = mVsyncChild->GetVsyncRate(); } // If hardware queries fail / are unsupported, we have to just guess. @@ -772,16 +742,11 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer { }; // RefreshDriverVsyncObserver ~VsyncRefreshDriverTimer() override { - if (XRE_IsParentProcess()) { + if (mVsyncDispatcher) { mVsyncDispatcher->RemoveChildRefreshTimer(mVsyncObserver); mVsyncDispatcher = nullptr; - } else { - // Since the PVsyncChild actors live through the life of the process, just - // send the unobserveVsync message to disable vsync event. We don't need - // to handle the cleanup stuff of this actor. PVsyncChild::ActorDestroy() - // will be called and clean up this actor. - Unused << mVsyncChild->SendUnobserve(); - mVsyncChild->SetVsyncObserver(nullptr); + } else if (mVsyncChild) { + mVsyncChild->RemoveChildRefreshTimer(mVsyncObserver); mVsyncChild = nullptr; } @@ -797,10 +762,10 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer { mLastFireTime = TimeStamp::Now(); - if (XRE_IsParentProcess()) { + if (mVsyncDispatcher) { mVsyncDispatcher->AddChildRefreshTimer(mVsyncObserver); - } else { - Unused << mVsyncChild->SendObserve(); + } else if (mVsyncChild) { + mVsyncChild->AddChildRefreshTimer(mVsyncObserver); mVsyncObserver->OnTimerStart(); } @@ -811,10 +776,10 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer { // Protect updates to `sActiveVsyncTimers`. MOZ_ASSERT(NS_IsMainThread()); - if (XRE_IsParentProcess()) { + if (mVsyncDispatcher) { mVsyncDispatcher->RemoveChildRefreshTimer(mVsyncObserver); - } else { - Unused << mVsyncChild->SendUnobserve(); + } else if (mVsyncChild) { + mVsyncChild->RemoveChildRefreshTimer(mVsyncObserver); } MOZ_ASSERT(sActiveVsyncTimers > 0); @@ -1006,34 +971,12 @@ class InactiveRefreshDriverTimer final } // namespace mozilla -static StaticRefPtr sRegularRateTimer; +static nsTArray sRegularRateTimers; static StaticRefPtr sThrottledRateTimer; -static void CreateContentVsyncRefreshTimer(void*) { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!XRE_IsParentProcess()); - - // Create the PVsync actor child for vsync-base refresh timer. - // PBackgroundChild is created synchronously. We will still use software - // timer before PVsync ready, and change to use hw timer when the connection - // is done. Please check nsRefreshDriver::PVsyncActorCreated(). - - PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread(); - if (NS_WARN_IF(!actorChild)) { - return; - } - - layout::PVsyncChild* actor = actorChild->SendPVsyncConstructor(); - if (NS_WARN_IF(!actor)) { - return; - } - - layout::VsyncChild* child = static_cast(actor); - nsRefreshDriver::PVsyncActorCreated(child); -} - void nsRefreshDriver::CreateVsyncRefreshTimer() { MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!mOwnTimer); PodArrayZero(sJankLevels); @@ -1042,32 +985,22 @@ void nsRefreshDriver::CreateVsyncRefreshTimer() { } // If available, we fetch the widget-specific vsync source. - // - // NOTE(heycam): If we are initializing an nsRefreshDriver under - // nsPresContext::Init, then this GetRootWidget() call will fail, as the - // pres context does not yet have a pres shell. For now, null check the - // pres shell to avoid a console warning. nsPresContext* pc = GetPresContext(); nsIWidget* widget = pc->GetPresShell() ? pc->GetRootWidget() : nullptr; if (widget) { - RefPtr localVsyncSource = widget->GetVsyncSource(); - if (localVsyncSource) { + if (RefPtr localVsyncSource = widget->GetVsyncSource()) { mOwnTimer = new VsyncRefreshDriverTimer(localVsyncSource); - return; + } else if (BrowserChild* browserChild = widget->GetOwningBrowserChild()) { + if (RefPtr localVsyncSource = browserChild->GetVsyncChild()) { + mOwnTimer = new VsyncRefreshDriverTimer(localVsyncSource); + } } } - if (XRE_IsParentProcess()) { - // Make sure all vsync systems are ready. - gfxPlatform::GetPlatform(); - // In parent process, we don't need to use ipc. We can create the - // VsyncRefreshDriverTimer directly. - sRegularRateTimer = new VsyncRefreshDriverTimer(); - return; + if (!mOwnTimer) { + mOwnTimer = new StartupRefreshDriverTimer(GetRegularTimerInterval()); } - - // If this process is not created by NUWA, just create the vsync timer here. - CreateContentVsyncRefreshTimer(nullptr); + sRegularRateTimers.AppendElement(mOwnTimer.get()); } static uint32_t GetFirstFrameDelay(imgIRequest* req) { @@ -1086,7 +1019,7 @@ static uint32_t GetFirstFrameDelay(imgIRequest* req) { /* static */ void nsRefreshDriver::Shutdown() { // clean up our timers - sRegularRateTimer = nullptr; + sRegularRateTimers.Clear(); sThrottledRateTimer = nullptr; } @@ -1142,26 +1075,10 @@ RefreshDriverTimer* nsRefreshDriver::ChooseTimer() { return sThrottledRateTimer; } - if (!sRegularRateTimer && !mOwnTimer) { - double rate = GetRegularTimerInterval(); - - // Try to use vsync-base refresh timer first for sRegularRateTimer. + if (!mOwnTimer) { CreateVsyncRefreshTimer(); - - if (mOwnTimer) { - return mOwnTimer.get(); - } - - if (!sRegularRateTimer) { - sRegularRateTimer = new StartupRefreshDriverTimer(rate); - } } - - if (mOwnTimer) { - return mOwnTimer.get(); - } - - return sRegularRateTimer; + return mOwnTimer.get(); } nsRefreshDriver::nsRefreshDriver(nsPresContext* aPresContext) @@ -1213,6 +1130,9 @@ nsRefreshDriver::~nsRefreshDriver() { mRootRefresh->RemoveRefreshObserver(this, FlushType::Style); mRootRefresh = nullptr; } + if (mOwnTimer) { + sRegularRateTimers.RemoveElement(mOwnTimer.get()); + } } // Method for testing. See nsIDOMWindowUtils.advanceTimeAndRefresh @@ -2675,21 +2595,6 @@ void nsRefreshDriver::SetThrottled(bool aThrottled) { nsPresContext* nsRefreshDriver::GetPresContext() const { return mPresContext; } -/*static*/ -void nsRefreshDriver::PVsyncActorCreated(VsyncChild* aVsyncChild) { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!XRE_IsParentProcess()); - RefPtr vsyncRefreshDriverTimer = - new VsyncRefreshDriverTimer(aVsyncChild); - - // If we are using software timer, swap current timer to - // VsyncRefreshDriverTimer. - if (sRegularRateTimer) { - sRegularRateTimer->SwapRefreshDrivers(vsyncRefreshDriverTimer); - } - sRegularRateTimer = std::move(vsyncRefreshDriverTimer); -} - void nsRefreshDriver::DoRefresh() { // Don't do a refresh unless we're in a state where we should be refreshing. if (!IsFrozen() && mPresContext && mActiveTimer) { @@ -2766,27 +2671,27 @@ TimeStamp nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!aDefault.IsNull()); - if (!sRegularRateTimer) { + if (sRegularRateTimers.IsEmpty()) { return aDefault; } // For computing idleness of refresh drivers we only care about - // sRegularRateTimer, since we consider refresh drivers attached to + // sRegularRateTimers, since we consider refresh drivers attached to // sThrottledRateTimer to be inactive. This implies that tasks // resulting from a tick on the sRegularRateTimer counts as being // busy but tasks resulting from a tick on sThrottledRateTimer // counts as being idle. - return sRegularRateTimer->GetIdleDeadlineHint(aDefault); + return sRegularRateTimers.ElementAt(0)->GetIdleDeadlineHint(aDefault); } /* static */ Maybe nsRefreshDriver::GetNextTickHint() { MOZ_ASSERT(NS_IsMainThread()); - if (!sRegularRateTimer) { + if (sRegularRateTimers.IsEmpty()) { return Nothing(); } - return sRegularRateTimer->GetNextTickHint(); + return sRegularRateTimers.ElementAt(0)->GetNextTickHint(); } void nsRefreshDriver::Disconnect() { diff --git a/layout/base/nsRefreshDriver.h b/layout/base/nsRefreshDriver.h index 67caea1b1d86..7eb4bce445e5 100644 --- a/layout/base/nsRefreshDriver.h +++ b/layout/base/nsRefreshDriver.h @@ -43,10 +43,6 @@ class PresShell; class RefreshDriverTimer; class Runnable; -namespace layout { -class VsyncChild; -} // namespace layout - } // namespace mozilla class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator, @@ -298,14 +294,6 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator, */ nsPresContext* GetPresContext() const; - /** - * PBackgroundChild actor is created asynchronously in content process. - * We can't create vsync-based timers during PBackground startup. This - * function will be called when PBackgroundChild actor is created. Then we can - * do the pending vsync-based timer creation. - */ - static void PVsyncActorCreated(mozilla::layout::VsyncChild* aVsyncChild); - void CreateVsyncRefreshTimer(); #ifdef DEBUG diff --git a/layout/base/nsRefreshObservers.h b/layout/base/nsRefreshObservers.h index a30667dccbf1..d46a8ddeaeb9 100644 --- a/layout/base/nsRefreshObservers.h +++ b/layout/base/nsRefreshObservers.h @@ -23,9 +23,6 @@ class AnimationEventDispatcher; class PendingFullscreenEvent; class PresShell; class RefreshDriverTimer; -namespace layout { -class VsyncChild; -} } // namespace mozilla /** diff --git a/layout/ipc/moz.build b/layout/ipc/moz.build index 30b05f96c943..fcb6b477b132 100644 --- a/layout/ipc/moz.build +++ b/layout/ipc/moz.build @@ -9,23 +9,12 @@ with Files("**"): EXPORTS.mozilla.layout += [ "RemoteLayerTreeOwner.h", - "VsyncChild.h", - "VsyncParent.h", ] UNIFIED_SOURCES += [ "RemoteLayerTreeOwner.cpp", ] -SOURCES += [ - "VsyncChild.cpp", - "VsyncParent.cpp", -] - -IPDL_SOURCES = [ - "PVsync.ipdl", -] - include("/ipc/chromium/chromium-config.mozbuild") FINAL_LIBRARY = "xul"