☠☠ backed out by 9b7e80071dec ☠ ☠ | |
author | Matt Woodrow <mwoodrow@mozilla.com> |
Fri, 07 Dec 2018 17:06:11 +0000 | |
changeset 449618 | ae190948ad730114399ac7074dbbf1cda2ebe359 |
parent 449617 | 0ade0aa77b2f2e04e15b4618c9ef1a74b8739777 |
child 449619 | d1ef6db7fc285d2d914ef98452033fc8517e1914 |
push id | 110403 |
push user | nerli@mozilla.com |
push date | Fri, 07 Dec 2018 22:18:43 +0000 |
treeherder | mozilla-inbound@904080f44dbd [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jrmuizel |
bugs | 1510853 |
milestone | 65.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/ipc/CompositorWidgetVsyncObserver.cpp +++ b/gfx/ipc/CompositorWidgetVsyncObserver.cpp @@ -13,19 +13,19 @@ namespace widget { CompositorWidgetVsyncObserver::CompositorWidgetVsyncObserver( RefPtr<VsyncBridgeChild> aVsyncBridge, const layers::LayersId& aRootLayerTreeId) : mVsyncBridge(aVsyncBridge), mRootLayerTreeId(aRootLayerTreeId) { MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(NS_IsMainThread()); } -bool CompositorWidgetVsyncObserver::NotifyVsync(TimeStamp aTimeStamp) { +bool CompositorWidgetVsyncObserver::NotifyVsync(const VsyncEvent& aVsync) { // Vsync notifications should only arrive on the vsync thread. MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(!NS_IsMainThread()); - mVsyncBridge->NotifyVsync(aTimeStamp, mRootLayerTreeId); + mVsyncBridge->NotifyVsync(aVsync, mRootLayerTreeId); return true; } } // namespace widget } // namespace mozilla
--- a/gfx/ipc/CompositorWidgetVsyncObserver.h +++ b/gfx/ipc/CompositorWidgetVsyncObserver.h @@ -19,17 +19,17 @@ namespace widget { class CompositorWidgetVsyncObserver : public VsyncObserver { typedef gfx::VsyncBridgeChild VsyncBridgeChild; public: CompositorWidgetVsyncObserver(RefPtr<VsyncBridgeChild> aVsyncBridge, const layers::LayersId& aRootLayerTreeId); - bool NotifyVsync(TimeStamp aVsyncTimestamp) override; + bool NotifyVsync(const VsyncEvent& aVsync) override; private: RefPtr<VsyncBridgeChild> mVsyncBridge; layers::LayersId mRootLayerTreeId; }; } // namespace widget } // namespace mozilla
--- a/gfx/ipc/PVsyncBridge.ipdl +++ b/gfx/ipc/PVsyncBridge.ipdl @@ -1,23 +1,24 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * 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/. */ using class mozilla::TimeStamp from "mozilla/TimeStamp.h"; using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h"; +using mozilla::VsyncEvent from "mozilla/VsyncDispatcher.h"; namespace mozilla { namespace gfx { // This protocol only serves one purpose: deliver vsync notifications from a // dedicated thread in the UI process to the compositor thread in the // compositor process. The child side exists in the UI process, and the // parent side in the GPU process. sync protocol PVsyncBridge { parent: - async NotifyVsync(TimeStamp vsyncTimeStamp, LayersId layersId); + async NotifyVsync(VsyncEvent vsync, LayersId layersId); }; } // namespace gfx } // namespace mozilla
--- a/gfx/ipc/VsyncBridgeChild.cpp +++ b/gfx/ipc/VsyncBridgeChild.cpp @@ -41,57 +41,56 @@ void VsyncBridgeChild::Open(Endpoint<PVs mLoop = MessageLoop::current(); // Last reference is freed in DeallocPVsyncBridgeChild. AddRef(); } class NotifyVsyncTask : public Runnable { public: - NotifyVsyncTask(RefPtr<VsyncBridgeChild> aVsyncBridge, TimeStamp aTimeStamp, - const layers::LayersId& aLayersId) + NotifyVsyncTask(RefPtr<VsyncBridgeChild> aVsyncBridge, + const VsyncEvent& aVsync, const layers::LayersId& aLayersId) : Runnable("gfx::NotifyVsyncTask"), mVsyncBridge(aVsyncBridge), - mTimeStamp(aTimeStamp), + mVsync(aVsync), mLayersId(aLayersId) {} NS_IMETHOD Run() override { - mVsyncBridge->NotifyVsyncImpl(mTimeStamp, mLayersId); + mVsyncBridge->NotifyVsyncImpl(mVsync, mLayersId); return NS_OK; } private: RefPtr<VsyncBridgeChild> mVsyncBridge; - TimeStamp mTimeStamp; + VsyncEvent mVsync; layers::LayersId mLayersId; }; bool VsyncBridgeChild::IsOnVsyncIOThread() const { return MessageLoop::current() == mLoop; } -void VsyncBridgeChild::NotifyVsync(TimeStamp aTimeStamp, +void VsyncBridgeChild::NotifyVsync(const VsyncEvent& aVsync, const layers::LayersId& aLayersId) { // This should be on the Vsync thread (not the Vsync I/O thread). MOZ_ASSERT(!IsOnVsyncIOThread()); - RefPtr<NotifyVsyncTask> task = - new NotifyVsyncTask(this, aTimeStamp, aLayersId); + RefPtr<NotifyVsyncTask> task = new NotifyVsyncTask(this, aVsync, aLayersId); mLoop->PostTask(task.forget()); } -void VsyncBridgeChild::NotifyVsyncImpl(TimeStamp aTimeStamp, +void VsyncBridgeChild::NotifyVsyncImpl(const VsyncEvent& aVsync, const layers::LayersId& aLayersId) { // This should be on the Vsync I/O thread. MOZ_ASSERT(IsOnVsyncIOThread()); if (!mProcessToken) { return; } - SendNotifyVsync(aTimeStamp, aLayersId); + SendNotifyVsync(aVsync, aLayersId); } void VsyncBridgeChild::Close() { if (!IsOnVsyncIOThread()) { mLoop->PostTask(NewRunnableMethod("gfx::VsyncBridgeChild::Close", this, &VsyncBridgeChild::Close)); return; }
--- a/gfx/ipc/VsyncBridgeChild.h +++ b/gfx/ipc/VsyncBridgeChild.h @@ -25,27 +25,28 @@ class VsyncBridgeChild final : public PV Endpoint<PVsyncBridgeChild>&& aEndpoint); void Close(); void ActorDestroy(ActorDestroyReason aWhy) override; void DeallocPVsyncBridgeChild() override; void ProcessingError(Result aCode, const char* aReason) override; - void NotifyVsync(TimeStamp aTimeStamp, const layers::LayersId& aLayersId); + void NotifyVsync(const VsyncEvent& aVsync, const layers::LayersId& aLayersId); virtual void HandleFatalError(const char* aMsg) const override; private: VsyncBridgeChild(RefPtr<VsyncIOThreadHolder>, const uint64_t& aProcessToken); ~VsyncBridgeChild(); void Open(Endpoint<PVsyncBridgeChild>&& aEndpoint); - void NotifyVsyncImpl(TimeStamp aTimeStamp, const layers::LayersId& aLayersId); + void NotifyVsyncImpl(const VsyncEvent& aVsync, + const layers::LayersId& aLayersId); bool IsOnVsyncIOThread() const; private: RefPtr<VsyncIOThreadHolder> mThread; MessageLoop* mLoop; uint64_t mProcessToken; };
--- a/gfx/ipc/VsyncBridgeParent.cpp +++ b/gfx/ipc/VsyncBridgeParent.cpp @@ -37,18 +37,18 @@ void VsyncBridgeParent::Open(Endpoint<PV // We can't recover from this. MOZ_CRASH("Failed to bind VsyncBridgeParent to endpoint"); } AddRef(); mOpen = true; } mozilla::ipc::IPCResult VsyncBridgeParent::RecvNotifyVsync( - const TimeStamp& aTimeStamp, const LayersId& aLayersId) { - CompositorBridgeParent::NotifyVsync(aTimeStamp, aLayersId); + const VsyncEvent& aVsync, const LayersId& aLayersId) { + CompositorBridgeParent::NotifyVsync(aVsync, aLayersId); return IPC_OK(); } void VsyncBridgeParent::Shutdown() { MessageLoop* ccloop = CompositorThreadHolder::Loop(); if (MessageLoop::current() != ccloop) { ccloop->PostTask(NewRunnableMethod("gfx::VsyncBridgeParent::ShutdownImpl", this, &VsyncBridgeParent::ShutdownImpl));
--- a/gfx/ipc/VsyncBridgeParent.h +++ b/gfx/ipc/VsyncBridgeParent.h @@ -18,17 +18,17 @@ namespace gfx { class VsyncBridgeParent final : public PVsyncBridgeParent { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncBridgeParent) static RefPtr<VsyncBridgeParent> Start( Endpoint<PVsyncBridgeParent>&& aEndpoint); - mozilla::ipc::IPCResult RecvNotifyVsync(const TimeStamp& vsyncTimeStamp, + mozilla::ipc::IPCResult RecvNotifyVsync(const VsyncEvent& aVsync, const LayersId& aLayersId) override; void ActorDestroy(ActorDestroyReason aWhy) override; void DeallocPVsyncBridgeParent() override; void Shutdown(); private: VsyncBridgeParent();
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -1567,32 +1567,32 @@ CompositorBridgeParent* CompositorBridge if (it == sCompositorMap->end()) { return nullptr; } CompositorBridgeParent* retval = it->second; sCompositorMap->erase(it); return retval; } -void CompositorBridgeParent::NotifyVsync(const TimeStamp& aTimeStamp, +void CompositorBridgeParent::NotifyVsync(const VsyncEvent& aVsync, const LayersId& aLayersId) { MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU); MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); MonitorAutoLock lock(*sIndirectLayerTreesLock); auto it = sIndirectLayerTrees.find(aLayersId); if (it == sIndirectLayerTrees.end()) return; CompositorBridgeParent* cbp = it->second.mParent; if (!cbp || !cbp->mWidget) return; RefPtr<VsyncObserver> obs = cbp->mWidget->GetVsyncObserver(); if (!obs) return; - obs->NotifyVsync(aTimeStamp); + obs->NotifyVsync(aVsync); } mozilla::ipc::IPCResult CompositorBridgeParent::RecvNotifyChildCreated( const LayersId& child, CompositorOptions* aOptions) { MonitorAutoLock lock(*sIndirectLayerTreesLock); NotifyChildCreated(child); *aOptions = mOptions; return IPC_OK();
--- a/gfx/layers/ipc/CompositorBridgeParent.h +++ b/gfx/layers/ipc/CompositorBridgeParent.h @@ -36,16 +36,17 @@ #include "mozilla/layers/MetricsSharingController.h" #include "mozilla/layers/PCompositorBridgeParent.h" #include "mozilla/layers/APZTestData.h" #include "mozilla/webrender/WebRenderTypes.h" #include "mozilla/widget/CompositorWidget.h" #include "nsISupportsImpl.h" #include "ThreadSafeRefcountingWithMainThreadDestruction.h" #include "mozilla/layers/UiCompositorControllerParent.h" +#include "mozilla/VsyncDispatcher.h" class MessageLoop; class nsIWidget; namespace mozilla { class CancelableRunnable; @@ -388,18 +389,17 @@ class CompositorBridgeParent final : pub * Returns a pointer to the CompositorBridgeParent corresponding to the given * ID. */ static CompositorBridgeParent* GetCompositorBridgeParent(uint64_t id); /** * Notify the compositor for the given layer tree that vsync has occurred. */ - static void NotifyVsync(const TimeStamp& aTimeStamp, - const LayersId& aLayersId); + static void NotifyVsync(const VsyncEvent& aVsync, const LayersId& aLayersId); /** * Set aController as the pan/zoom callback for the subtree referred * to by aLayersId. * * Must run on content main thread. */ static void SetControllerForLayerTree(LayersId aLayersId,
--- a/gfx/layers/ipc/CompositorVsyncScheduler.cpp +++ b/gfx/layers/ipc/CompositorVsyncScheduler.cpp @@ -43,23 +43,22 @@ namespace layers { using namespace mozilla::gfx; using namespace std; CompositorVsyncScheduler::Observer::Observer(CompositorVsyncScheduler* aOwner) : mMutex("CompositorVsyncScheduler.Observer.Mutex"), mOwner(aOwner) {} CompositorVsyncScheduler::Observer::~Observer() { MOZ_ASSERT(!mOwner); } -bool CompositorVsyncScheduler::Observer::NotifyVsync( - TimeStamp aVsyncTimestamp) { +bool CompositorVsyncScheduler::Observer::NotifyVsync(const VsyncEvent& aVsync) { MutexAutoLock lock(mMutex); if (!mOwner) { return false; } - return mOwner->NotifyVsync(aVsyncTimestamp); + return mOwner->NotifyVsync(aVsync); } void CompositorVsyncScheduler::Observer::Destroy() { MutexAutoLock lock(mMutex); mOwner = nullptr; } CompositorVsyncScheduler::CompositorVsyncScheduler( @@ -162,26 +161,26 @@ void CompositorVsyncScheduler::ScheduleC // through the main thread of the UI process. It's possible that // we're blocking there waiting on a composite, so schedule an initial // one now to get things started. PostCompositeTask(TimeStamp::Now()); } } } -bool CompositorVsyncScheduler::NotifyVsync(TimeStamp aVsyncTimestamp) { +bool CompositorVsyncScheduler::NotifyVsync(const VsyncEvent& aVsync) { // Called from the vsync dispatch thread. When in the GPU Process, that's // the same as the compositor thread. MOZ_ASSERT_IF(XRE_IsParentProcess(), !CompositorThreadHolder::IsInCompositorThread()); MOZ_ASSERT_IF(XRE_GetProcessType() == GeckoProcessType_GPU, CompositorThreadHolder::IsInCompositorThread()); MOZ_ASSERT(!NS_IsMainThread()); - PostCompositeTask(aVsyncTimestamp); - PostVRTask(aVsyncTimestamp); + PostCompositeTask(aVsync.mTime); + PostVRTask(aVsync.mTime); return true; } void CompositorVsyncScheduler::CancelCurrentCompositeTask() { MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread() || NS_IsMainThread()); MonitorAutoLock lock(mCurrentCompositeTaskMonitor); if (mCurrentCompositeTask) {
--- a/gfx/layers/ipc/CompositorVsyncScheduler.h +++ b/gfx/layers/ipc/CompositorVsyncScheduler.h @@ -43,17 +43,17 @@ class CompositorVsyncScheduler { explicit CompositorVsyncScheduler( CompositorVsyncSchedulerOwner* aVsyncSchedulerOwner, widget::CompositorWidget* aWidget); /** * Notify this class of a vsync. This will trigger a composite if one is * needed. This must be called from the vsync dispatch thread. */ - bool NotifyVsync(TimeStamp aVsyncTimestamp); + bool NotifyVsync(const VsyncEvent& aVsync); /** * Do cleanup. This must be called on the compositor thread. */ void Destroy(); /** * Notify this class that a composition is needed. This will trigger a @@ -121,17 +121,17 @@ class CompositorVsyncScheduler { void ObserveVsync(); void UnobserveVsync(); void DispatchVREvents(TimeStamp aVsyncTimestamp); class Observer final : public VsyncObserver { public: explicit Observer(CompositorVsyncScheduler* aOwner); - virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) override; + virtual bool NotifyVsync(const VsyncEvent& aVsync) override; void Destroy(); private: virtual ~Observer(); Mutex mMutex; // Hold raw pointer to avoid mutual reference. CompositorVsyncScheduler* mOwner;
--- a/gfx/layers/ipc/LayersMessageUtils.h +++ b/gfx/layers/ipc/LayersMessageUtils.h @@ -19,16 +19,17 @@ #include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/FocusTarget.h" #include "mozilla/layers/GeckoContentController.h" #include "mozilla/layers/KeyboardMap.h" #include "mozilla/layers/LayerAttributes.h" #include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/RefCountedShmem.h" #include "mozilla/layers/RepaintRequest.h" +#include "VsyncSource.h" #include "mozilla/Move.h" #include <stdint.h> #ifdef _MSC_VER #pragma warning(disable : 4800) #endif @@ -38,16 +39,35 @@ template <> struct ParamTraits<mozilla::layers::LayersId> : public PlainOldDataSerializer<mozilla::layers::LayersId> {}; template <typename T> struct ParamTraits<mozilla::layers::BaseTransactionId<T>> : public PlainOldDataSerializer<mozilla::layers::BaseTransactionId<T>> {}; template <> +struct ParamTraits<mozilla::VsyncId> + : public PlainOldDataSerializer<mozilla::VsyncId> {}; + +template <> +struct ParamTraits<mozilla::VsyncEvent> { + typedef mozilla::VsyncEvent paramType; + + static void Write(Message* msg, const paramType& param) { + WriteParam(msg, param.mId); + WriteParam(msg, param.mTime); + } + static bool Read(const Message* msg, PickleIterator* iter, + paramType* result) { + return ReadParam(msg, iter, &result->mId) && + ReadParam(msg, iter, &result->mTime); + } +}; + +template <> struct ParamTraits<mozilla::layers::LayersObserverEpoch> : public PlainOldDataSerializer<mozilla::layers::LayersObserverEpoch> {}; template <> struct ParamTraits<mozilla::layers::LayersBackend> : public ContiguousEnumSerializer< mozilla::layers::LayersBackend, mozilla::layers::LayersBackend::LAYERS_NONE,
--- a/gfx/tests/gtest/TestVsync.cpp +++ b/gfx/tests/gtest/TestVsync.cpp @@ -25,17 +25,17 @@ using ::testing::_; // Windows 8.1 has intermittents at 50 ms. Raise limit to 5 vsync intervals. const int kVsyncTimeoutMS = 80; class TestVsyncObserver : public VsyncObserver { public: TestVsyncObserver() : mDidGetVsyncNotification(false), mVsyncMonitor("VsyncMonitor") {} - virtual bool NotifyVsync(TimeStamp aVsyncTimeStamp) override { + virtual bool NotifyVsync(const VsyncEvent& aVsync) override { MonitorAutoLock lock(mVsyncMonitor); mDidGetVsyncNotification = true; mVsyncMonitor.Notify(); return true; } void WaitForVsyncNotification() { MOZ_ASSERT(NS_IsMainThread());
--- a/gfx/thebes/VsyncSource.cpp +++ b/gfx/thebes/VsyncSource.cpp @@ -50,21 +50,24 @@ VsyncSource::Display::~Display() { mRefreshTimerVsyncDispatcher = nullptr; mCompositorVsyncDispatchers.Clear(); } void VsyncSource::Display::NotifyVsync(TimeStamp aVsyncTimestamp) { // Called on the vsync thread MutexAutoLock lock(mDispatcherLock); + mVsyncId = mVsyncId.Next(); + VsyncEvent event(mVsyncId, aVsyncTimestamp); + for (size_t i = 0; i < mCompositorVsyncDispatchers.Length(); i++) { - mCompositorVsyncDispatchers[i]->NotifyVsync(aVsyncTimestamp); + mCompositorVsyncDispatchers[i]->NotifyVsync(event); } - mRefreshTimerVsyncDispatcher->NotifyVsync(aVsyncTimestamp); + mRefreshTimerVsyncDispatcher->NotifyVsync(event); } TimeDuration VsyncSource::Display::GetVsyncRate() { // If hardware queries fail / are unsupported, we have to just guess. return TimeDuration::FromMilliseconds(1000.0 / 60.0); } void VsyncSource::Display::AddCompositorVsyncDispatcher(
--- a/gfx/thebes/VsyncSource.h +++ b/gfx/thebes/VsyncSource.h @@ -6,22 +6,31 @@ #ifndef GFX_VSYNCSOURCE_H #define GFX_VSYNCSOURCE_H #include "nsTArray.h" #include "mozilla/RefPtr.h" #include "mozilla/Mutex.h" #include "mozilla/TimeStamp.h" #include "nsISupportsImpl.h" +#include "mozilla/layers/LayersTypes.h" namespace mozilla { class RefreshTimerVsyncDispatcher; class CompositorVsyncDispatcher; +class VsyncIdType {}; +typedef layers::BaseTransactionId<VsyncIdType> VsyncId; + +namespace layout { +class PVsyncChild; +} + namespace gfx { +class PVsyncBridgeParent; // Controls how and when to enable/disable vsync. Lives as long as the // gfxPlatform does on the parent process class VsyncSource { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncSource) typedef mozilla::RefreshTimerVsyncDispatcher RefreshTimerVsyncDispatcher; typedef mozilla::CompositorVsyncDispatcher CompositorVsyncDispatcher; @@ -61,27 +70,49 @@ class VsyncSource { private: void UpdateVsyncStatus(); Mutex mDispatcherLock; bool mRefreshTimerNeedsVsync; nsTArray<RefPtr<CompositorVsyncDispatcher>> mCompositorVsyncDispatchers; RefPtr<RefreshTimerVsyncDispatcher> mRefreshTimerVsyncDispatcher; + VsyncId mVsyncId; }; void AddCompositorVsyncDispatcher( CompositorVsyncDispatcher* aCompositorVsyncDispatcher); void RemoveCompositorVsyncDispatcher( CompositorVsyncDispatcher* aCompositorVsyncDispatcher); RefPtr<RefreshTimerVsyncDispatcher> GetRefreshTimerVsyncDispatcher(); virtual Display& GetGlobalDisplay() = 0; // Works across all displays void Shutdown(); protected: virtual ~VsyncSource() {} }; } // namespace gfx + +namespace recordreplay { +namespace child { +void NotifyVsyncObserver(); +} +} // namespace recordreplay + +struct VsyncEvent { + VsyncId mId; + TimeStamp mTime; + + private: + VsyncEvent(const VsyncId& aId, const TimeStamp& aTime) + : mId(aId), mTime(aTime) {} + VsyncEvent() {} + friend class gfx::VsyncSource::Display; + friend class gfx::PVsyncBridgeParent; + friend class layout::PVsyncChild; + friend void recordreplay::child::NotifyVsyncObserver(); +}; + } // namespace mozilla #endif /* GFX_VSYNCSOURCE_H */
--- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -496,55 +496,55 @@ class VsyncRefreshDriverTimer : public R private: ~ParentProcessVsyncNotifier() {} RefPtr<RefreshDriverVsyncObserver> mObserver; TimeStamp mVsyncTimestamp; static mozilla::Atomic<bool> sHighPriorityEnabled; }; - bool NotifyVsync(TimeStamp aVsyncTimestamp) override { + bool NotifyVsync(const VsyncEvent& aVsync) override { // IMPORTANT: All paths through this method MUST hold a strong ref on // |this| for the duration of the TickRefreshDriver callback. if (!NS_IsMainThread()) { MOZ_ASSERT(XRE_IsParentProcess()); // Compress vsync notifications such that only 1 may run at a time // This is so that we don't flood the refresh driver with vsync messages // if the main thread is blocked for long periods of time { // scope lock MonitorAutoLock lock(mRefreshTickLock); - mRecentVsync = aVsyncTimestamp; + mRecentVsync = aVsync.mTime; if (!mProcessedVsync) { return true; } mProcessedVsync = false; } nsCOMPtr<nsIRunnable> vsyncEvent = - new ParentProcessVsyncNotifier(this, aVsyncTimestamp); + new ParentProcessVsyncNotifier(this, aVsync.mTime); NS_DispatchToMainThread(vsyncEvent); } else { - mRecentVsync = aVsyncTimestamp; - if (!mBlockUntil.IsNull() && mBlockUntil > aVsyncTimestamp) { + mRecentVsync = aVsync.mTime; + if (!mBlockUntil.IsNull() && mBlockUntil > aVsync.mTime) { if (mProcessedVsync) { // Re-post vsync update as a normal priority runnable. This way // runnables already in normal priority queue get processed. mProcessedVsync = false; nsCOMPtr<nsIRunnable> vsyncEvent = NewRunnableMethod<>( "RefreshDriverVsyncObserver::NormalPriorityNotify", this, &RefreshDriverVsyncObserver::NormalPriorityNotify); NS_DispatchToMainThread(vsyncEvent); } return true; } RefPtr<RefreshDriverVsyncObserver> kungFuDeathGrip(this); - TickRefreshDriver(aVsyncTimestamp); + TickRefreshDriver(aVsync.mTime); } return true; } void Shutdown() { MOZ_ASSERT(NS_IsMainThread()); mVsyncRefreshDriverTimer = nullptr;
--- a/layout/ipc/PVsync.ipdl +++ b/layout/ipc/PVsync.ipdl @@ -2,32 +2,33 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * 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/. */ include protocol PBackground; include "mozilla/layers/LayersMessageUtils.h"; using class mozilla::TimeStamp from "mozilla/TimeStamp.h"; +using mozilla::VsyncEvent from "mozilla/VsyncDispatcher.h"; namespace mozilla { namespace layout { /* * 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 * interfaces for content to observe/unobserve vsync event notifications. */ async protocol PVsync { manager PBackground; child: // Send vsync event from chrome to content process. - prio(high) async Notify(TimeStamp aVsyncTimestamp) compress; + prio(high) async Notify(VsyncEvent aVsync) compress; // Send the vsync rate to the content process. async VsyncRate(float aVsyncRate); parent: // Content process use these messages to acquire the vsync event. async Observe(); async Unobserve();
--- a/layout/ipc/VsyncChild.cpp +++ b/layout/ipc/VsyncChild.cpp @@ -46,29 +46,28 @@ void VsyncChild::ActorDestroy(ActorDestr mIsShutdown = true; mObserver = nullptr; if (recordreplay::IsRecordingOrReplaying()) { recordreplay::child::SetVsyncObserver(nullptr); } } -mozilla::ipc::IPCResult VsyncChild::RecvNotify( - const TimeStamp& aVsyncTimestamp) { +mozilla::ipc::IPCResult VsyncChild::RecvNotify(const VsyncEvent& aVsync) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mIsShutdown); SchedulerGroup::MarkVsyncRan(); if (mObservingVsync && mObserver) { if (recordreplay::IsRecordingOrReplaying() && !recordreplay::child::OnVsync()) { return IPC_OK(); } - mObserver->NotifyVsync(aVsyncTimestamp); + mObserver->NotifyVsync(aVsync); } return IPC_OK(); } void VsyncChild::SetVsyncObserver(VsyncObserver* aVsyncObserver) { MOZ_ASSERT(NS_IsMainThread()); mObserver = aVsyncObserver;
--- a/layout/ipc/VsyncChild.h +++ b/layout/ipc/VsyncChild.h @@ -47,18 +47,17 @@ class VsyncChild final : public PVsyncCh // TimeDuration::Forever() if mVsyncRate hasn't been set by calling // GetVsyncRate. TimeDuration VsyncRate(); private: VsyncChild(); virtual ~VsyncChild(); - virtual mozilla::ipc::IPCResult RecvNotify( - const TimeStamp& aVsyncTimestamp) override; + virtual mozilla::ipc::IPCResult RecvNotify(const VsyncEvent& aVsync) override; virtual mozilla::ipc::IPCResult RecvVsyncRate( const float& aVsyncRate) override; virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override; bool mObservingVsync; bool mIsShutdown; // The content side vsync observer.
--- a/layout/ipc/VsyncParent.cpp +++ b/layout/ipc/VsyncParent.cpp @@ -37,37 +37,37 @@ VsyncParent::VsyncParent() AssertIsOnBackgroundThread(); } VsyncParent::~VsyncParent() { // Since we use NS_INLINE_DECL_THREADSAFE_REFCOUNTING, we can't make sure // VsyncParent is always released on the background thread. } -bool VsyncParent::NotifyVsync(TimeStamp aTimeStamp) { +bool VsyncParent::NotifyVsync(const VsyncEvent& aVsync) { // Called on hardware vsync thread. We should post to current ipc thread. MOZ_ASSERT(!IsOnBackgroundThread()); - nsCOMPtr<nsIRunnable> vsyncEvent = NewRunnableMethod<TimeStamp>( + nsCOMPtr<nsIRunnable> vsyncEvent = NewRunnableMethod<VsyncEvent>( "layout::VsyncParent::DispatchVsyncEvent", this, - &VsyncParent::DispatchVsyncEvent, aTimeStamp); + &VsyncParent::DispatchVsyncEvent, aVsync); MOZ_ALWAYS_SUCCEEDS( mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL)); return true; } -void VsyncParent::DispatchVsyncEvent(TimeStamp aTimeStamp) { +void VsyncParent::DispatchVsyncEvent(const VsyncEvent& aVsync) { AssertIsOnBackgroundThread(); // If we call NotifyVsync() when we handle ActorDestroy() message, we might // still call DispatchVsyncEvent(). // Similarly, we might also receive RecvUnobserveVsync() when call // NotifyVsync(). We use mObservingVsync and mDestroyed flags to skip this // notification. if (mObservingVsync && !mDestroyed) { - Unused << SendNotify(aTimeStamp); + Unused << SendNotify(aVsync); } } mozilla::ipc::IPCResult VsyncParent::RecvRequestVsyncRate() { AssertIsOnBackgroundThread(); TimeDuration vsyncRate = gfxPlatform::GetPlatform() ->GetHardwareVsync() ->GetGlobalDisplay()
--- a/layout/ipc/VsyncParent.h +++ b/layout/ipc/VsyncParent.h @@ -29,24 +29,24 @@ class VsyncParent final : public PVsyncP friend class mozilla::ipc::BackgroundParentImpl; private: static already_AddRefed<VsyncParent> Create(); VsyncParent(); virtual ~VsyncParent(); - virtual bool NotifyVsync(TimeStamp aTimeStamp) override; + virtual bool NotifyVsync(const VsyncEvent& aVsync) override; virtual mozilla::ipc::IPCResult RecvRequestVsyncRate() override; virtual mozilla::ipc::IPCResult RecvObserve() override; virtual mozilla::ipc::IPCResult RecvUnobserve() override; virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override; - void DispatchVsyncEvent(TimeStamp aTimeStamp); + void DispatchVsyncEvent(const VsyncEvent& aVsync); bool mObservingVsync; bool mDestroyed; nsCOMPtr<nsIThread> mBackgroundThread; RefPtr<RefreshTimerVsyncDispatcher> mVsyncDispatcher; }; } // namespace layout
--- a/toolkit/recordreplay/ipc/ChildIPC.cpp +++ b/toolkit/recordreplay/ipc/ChildIPC.cpp @@ -409,19 +409,22 @@ void NotifyAlwaysMarkMajorCheckpoints() static VsyncObserver* gVsyncObserver; void SetVsyncObserver(VsyncObserver* aObserver) { MOZ_RELEASE_ASSERT(!gVsyncObserver || !aObserver); gVsyncObserver = aObserver; } -static void NotifyVsyncObserver() { +void NotifyVsyncObserver() { if (gVsyncObserver) { - gVsyncObserver->NotifyVsync(TimeStamp::Now()); + static VsyncId vsyncId; + vsyncId = vsyncId.Next(); + VsyncEvent event(vsyncId, TimeStamp::Now()); + gVsyncObserver->NotifyVsync(event); } } // How many paints have been started and haven't reached PaintFromMainThread // yet. Only accessed on the main thread. static int32_t gNumPendingMainThreadPaints; bool OnVsync() {
--- a/widget/VsyncDispatcher.cpp +++ b/widget/VsyncDispatcher.cpp @@ -22,24 +22,23 @@ CompositorVsyncDispatcher::CompositorVsy } CompositorVsyncDispatcher::~CompositorVsyncDispatcher() { MOZ_ASSERT(XRE_IsParentProcess()); // We auto remove this vsync dispatcher from the vsync source in the // nsBaseWidget } -void CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp) { +void CompositorVsyncDispatcher::NotifyVsync(const VsyncEvent& aVsync) { // In vsync thread - layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker( - aVsyncTimestamp); + layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(aVsync.mTime); MutexAutoLock lock(mCompositorObserverLock); if (mCompositorVsyncObserver) { - mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp); + mCompositorVsyncObserver->NotifyVsync(aVsync); } } void CompositorVsyncDispatcher::ObserveVsync(bool aEnable) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(XRE_IsParentProcess()); if (mDidShutdown) { return; @@ -96,25 +95,25 @@ RefreshTimerVsyncDispatcher::RefreshTime MOZ_ASSERT(NS_IsMainThread()); } RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher() { MOZ_ASSERT(XRE_IsParentProcess() || recordreplay::IsRecordingOrReplaying()); MOZ_ASSERT(NS_IsMainThread()); } -void RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp) { +void RefreshTimerVsyncDispatcher::NotifyVsync(const VsyncEvent& aVsync) { MutexAutoLock lock(mRefreshTimersLock); for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) { - mChildRefreshTimers[i]->NotifyVsync(aVsyncTimestamp); + mChildRefreshTimers[i]->NotifyVsync(aVsync); } if (mParentRefreshTimer) { - mParentRefreshTimer->NotifyVsync(aVsyncTimestamp); + mParentRefreshTimer->NotifyVsync(aVsync); } } void RefreshTimerVsyncDispatcher::SetParentRefreshTimer( VsyncObserver* aVsyncObserver) { MOZ_ASSERT(NS_IsMainThread()); { // lock scope because UpdateVsyncStatus runs on main thread and will // deadlock
--- a/widget/VsyncDispatcher.h +++ b/widget/VsyncDispatcher.h @@ -6,29 +6,30 @@ #ifndef mozilla_widget_VsyncDispatcher_h #define mozilla_widget_VsyncDispatcher_h #include "mozilla/Mutex.h" #include "mozilla/TimeStamp.h" #include "nsISupportsImpl.h" #include "nsTArray.h" #include "mozilla/RefPtr.h" +#include "VsyncSource.h" namespace mozilla { class VsyncObserver { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncObserver) public: // The method called when a vsync occurs. Return true if some work was done. // In general, this vsync notification will occur on the hardware vsync // thread from VsyncSource. But it might also be called on PVsync ipc thread // if this notification is cross process. Thus all observer should check the // thread model before handling the real task. - virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) = 0; + virtual bool NotifyVsync(const VsyncEvent& aVsync) = 0; protected: VsyncObserver() {} virtual ~VsyncObserver() {} }; // VsyncObserver // Used to dispatch vsync events in the parent process to compositors. // @@ -44,17 +45,17 @@ class VsyncObserver { // compositor thread in the compositor process. class CompositorVsyncDispatcher final { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorVsyncDispatcher) public: CompositorVsyncDispatcher(); // Called on the vsync thread when a hardware vsync occurs - void NotifyVsync(TimeStamp aVsyncTimestamp); + void NotifyVsync(const VsyncEvent& aVsync); // Compositor vsync observers must be added/removed on the compositor thread void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver); void Shutdown(); private: virtual ~CompositorVsyncDispatcher(); void ObserveVsync(bool aEnable); @@ -67,17 +68,17 @@ class CompositorVsyncDispatcher final { // Dispatch vsync event to ipc actor parent and chrome RefreshTimer. class RefreshTimerVsyncDispatcher final { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefreshTimerVsyncDispatcher) public: RefreshTimerVsyncDispatcher(); // Please check CompositorVsyncDispatcher::NotifyVsync(). - void NotifyVsync(TimeStamp aVsyncTimestamp); + void NotifyVsync(const VsyncEvent& aVsync); // Set chrome process's RefreshTimer to this dispatcher. // This function can be called from any thread. void SetParentRefreshTimer(VsyncObserver* aVsyncObserver); // Add or remove the content process' RefreshTimer to this dispatcher. This // will be a no-op for AddChildRefreshTimer() if the observer is already // registered.