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 527d2186c2a0..cc5ba25fd17e 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,29 @@ IPCResult BrowserParent::RecvNewWindowGlobal( return IPC_OK(); } +PVsyncParent* BrowserParent::AllocPVsyncParent() { + MOZ_ASSERT(!mVsyncParent); + mVsyncParent = new VsyncParent(); + UpdateVsyncParentVsyncSource(); + return mVsyncParent.get(); +} + +bool BrowserParent::DeallocPVsyncParent(PVsyncParent* aActor) { + MOZ_ASSERT(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 65% rename from layout/ipc/PVsync.ipdl rename to dom/ipc/PVsync.ipdl index 6cca91cb4bc1..19fdc4164d5f 100644 --- a/layout/ipc/PVsync.ipdl +++ b/dom/ipc/PVsync.ipdl @@ -4,41 +4,37 @@ * 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. - prio(high) async Notify(VsyncEvent aVsync) compress; - - // Send the vsync rate to the content process. - async VsyncRate(float aVsyncRate); + // Send vsync event and vsync rate from chrome to content process. + prio(high) async Notify(VsyncEvent aVsync, float aVsyncRate) compress; parent: // Content process use these messages to acquire the vsync event. async Observe(); async Unobserve(); - 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 60% rename from layout/ipc/VsyncChild.cpp rename to dom/ipc/VsyncChild.cpp index 1d358fe8e677..ef0b3524b6cc 100644 --- a/layout/ipc/VsyncChild.cpp +++ b/dom/ipc/VsyncChild.cpp @@ -10,17 +10,17 @@ #include "mozilla/VsyncDispatcher.h" #include "nsThreadUtils.h" -namespace mozilla::layout { +namespace mozilla::dom { VsyncChild::VsyncChild() - : mObservingVsync(false), - mIsShutdown(false), + : mIsShutdown(false), mVsyncRate(TimeDuration::Forever()) { 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,43 +38,61 @@ 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) { +mozilla::ipc::IPCResult VsyncChild::RecvNotify(const VsyncEvent& aVsync, + const float& aVsyncRate) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mIsShutdown); SchedulerGroup::MarkVsyncRan(); - if (mObservingVsync && mObserver) { - mObserver->NotifyVsync(aVsync); + + mVsyncRate = TimeDuration::FromMilliseconds(aVsyncRate); + + 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()) { - PVsyncChild::SendRequestVsyncRate(); - } - 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 68% rename from layout/ipc/VsyncChild.h rename to dom/ipc/VsyncChild.h index 23c915f3358f..ad057b58ce5b 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,15 +25,17 @@ 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); + + TimeDuration GetVsyncRate(); + + /* // Bind a VsyncObserver into VsyncChild after ipc channel connected. void SetVsyncObserver(VsyncObserver* aVsyncObserver); // GetVsyncRate is a getter for mVsyncRate which sends a requests to @@ -48,24 +47,21 @@ class VsyncChild final : public PVsyncChild { // 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); + mozilla::ipc::IPCResult RecvNotify(const VsyncEvent& aVsync, + const float& aVsyncRate); virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override; - bool mObservingVsync; bool mIsShutdown; - - // The content side vsync observer. - RefPtr mObserver; TimeDuration mVsyncRate; + 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 55% rename from layout/ipc/VsyncParent.cpp rename to dom/ipc/VsyncParent.cpp index c039af999b39..46f66f3c4eab 100644 --- a/layout/ipc/VsyncParent.cpp +++ b/dom/ipc/VsyncParent.cpp @@ -13,48 +13,45 @@ #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(). @@ -62,22 +59,13 @@ void VsyncParent::DispatchVsyncEvent(const VsyncEvent& aVsync) { // NotifyVsync(). We use mObservingVsync and mDestroyed flags to skip this // notification. if (mObservingVsync && !mDestroyed) { - Unused << SendNotify(aVsync); + TimeDuration vsyncRate = mVsyncSource->GetGlobalDisplay().GetVsyncRate(); + Unused << SendNotify(aVsync, vsyncRate.ToMilliseconds()); } } -mozilla::ipc::IPCResult VsyncParent::RecvRequestVsyncRate() { - AssertIsOnBackgroundThread(); - TimeDuration vsyncRate = gfxPlatform::GetPlatform() - ->GetHardwareVsync() - ->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 +75,7 @@ mozilla::ipc::IPCResult VsyncParent::RecvObserve() { } mozilla::ipc::IPCResult VsyncParent::RecvUnobserve() { - AssertIsOnBackgroundThread(); + AssertIsOnInitialThread(); if (mObservingVsync) { mVsyncDispatcher->RemoveChildRefreshTimer(this); mObservingVsync = false; @@ -96,9 +84,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 +94,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 67% rename from layout/ipc/VsyncParent.h rename to dom/ipc/VsyncParent.h index 2d0885d81a7a..af452fd508ce 100644 --- a/layout/ipc/VsyncParent.h +++ b/dom/ipc/VsyncParent.h @@ -4,53 +4,51 @@ * 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(); + virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override; mozilla::ipc::IPCResult RecvObserve(); mozilla::ipc::IPCResult RecvUnobserve(); - virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override; void DispatchVsyncEvent(const VsyncEvent& aVsync); + void UpdateVsyncRate(); + + 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..bfce7ec5ca82 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,48 @@ class SimpleTimerBasedRefreshDriverTimer : public RefreshDriverTimer { */ class VsyncRefreshDriverTimer : public RefreshDriverTimer { public: - VsyncRefreshDriverTimer() : mVsyncChild(nullptr) { + VsyncRefreshDriverTimer() + : mVsyncDispatcher(nullptr), + 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), + mVsyncDispatcher(nullptr), + 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 +745,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 +765,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 +779,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); @@ -1007,33 +975,12 @@ class InactiveRefreshDriverTimer final } // namespace mozilla static StaticRefPtr sRegularRateTimer; +static nsTArray* sRegularRateTimerList; 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 +989,29 @@ 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; + nsIWidget* widget = pc->GetRootWidget(); if (widget) { - RefPtr localVsyncSource = widget->GetVsyncSource(); - if (localVsyncSource) { + if (RefPtr localVsyncSource = widget->GetVsyncSource()) { mOwnTimer = new VsyncRefreshDriverTimer(localVsyncSource); + sRegularRateTimerList->AppendElement(mOwnTimer.get()); return; } + if (BrowserChild* browserChild = widget->GetOwningBrowserChild()) { + if (RefPtr localVsyncSource = browserChild->GetVsyncChild()) { + mOwnTimer = new VsyncRefreshDriverTimer(localVsyncSource); + sRegularRateTimerList->AppendElement(mOwnTimer.get()); + return; + } + } } - - if (XRE_IsParentProcess()) { + if (!sRegularRateTimer && 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. + // In parent process, we can create the VsyncRefreshDriverTimer directly. sRegularRateTimer = new VsyncRefreshDriverTimer(); - return; + sRegularRateTimerList->AppendElement(sRegularRateTimer); } - - // If this process is not created by NUWA, just create the vsync timer here. - CreateContentVsyncRefreshTimer(nullptr); } static uint32_t GetFirstFrameDelay(imgIRequest* req) { @@ -1085,8 +1029,11 @@ static uint32_t GetFirstFrameDelay(imgIRequest* req) { /* static */ void nsRefreshDriver::Shutdown() { + MOZ_ASSERT(NS_IsMainThread()); // clean up our timers sRegularRateTimer = nullptr; + delete sRegularRateTimerList; + sRegularRateTimerList = nullptr; sThrottledRateTimer = nullptr; } @@ -1142,25 +1089,20 @@ 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(); } + if (!sRegularRateTimer) { + double rate = GetRegularTimerInterval(); + sRegularRateTimer = new StartupRefreshDriverTimer(rate); + sRegularRateTimerList->AppendElement(sRegularRateTimer); + } + return sRegularRateTimer; } @@ -1196,6 +1138,9 @@ nsRefreshDriver::nsRefreshDriver(nsPresContext* aPresContext) mNextThrottledFrameRequestTick = mMostRecentRefresh; mNextRecomputeVisibilityTick = mMostRecentRefresh; + if (!sRegularRateTimerList) { + sRegularRateTimerList = new nsTArray(); + } ++sRefreshDriverCount; } @@ -1213,6 +1158,9 @@ nsRefreshDriver::~nsRefreshDriver() { mRootRefresh->RemoveRefreshObserver(this, FlushType::Style); mRootRefresh = nullptr; } + if (mOwnTimer && sRegularRateTimerList) { + sRegularRateTimerList->RemoveElement(mOwnTimer.get()); + } } // Method for testing. See nsIDOMWindowUtils.advanceTimeAndRefresh @@ -2675,21 +2623,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 +2699,40 @@ TimeStamp nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!aDefault.IsNull()); - if (!sRegularRateTimer) { - return aDefault; - } - // For computing idleness of refresh drivers we only care about - // sRegularRateTimer, since we consider refresh drivers attached to + // sRegularRateTimerList, 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); + TimeStamp hint = aDefault; + if (sRegularRateTimerList) { + for (RefreshDriverTimer* timer : *sRegularRateTimerList) { + TimeStamp newHint = timer->GetIdleDeadlineHint(aDefault); + if (newHint > hint) { + hint = newHint; + } + } + } + return hint; } /* static */ Maybe nsRefreshDriver::GetNextTickHint() { MOZ_ASSERT(NS_IsMainThread()); - if (!sRegularRateTimer) { - return Nothing(); + Maybe hint = Nothing(); + if (sRegularRateTimerList) { + for (RefreshDriverTimer* timer : *sRegularRateTimerList) { + Maybe newHint = timer->GetNextTickHint(); + if ((newHint.isSome() && hint.isNothing()) || + (newHint.isSome() && hint.isSome() && + newHint.value() > hint.value())) { + hint = newHint; + } + } } - return sRegularRateTimer->GetNextTickHint(); + return hint; } 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"