Bug 1184283 - change PVsync to implement gfx::VsyncSource, and to track a gfx::VsyncSource on parent
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -225,19 +225,19 @@ BackgroundChildImpl::DeallocPFileDescrip
{
MOZ_ASSERT(aActor);
delete static_cast<FileDescriptorSetChild*>(aActor);
return true;
}
BackgroundChildImpl::PVsyncChild*
-BackgroundChildImpl::AllocPVsyncChild()
+BackgroundChildImpl::AllocPVsyncChild(const nsID& aDisplayIdentifier)
{
- RefPtr<mozilla::layout::VsyncChild> actor = new mozilla::layout::VsyncChild();
+ RefPtr<mozilla::layout::VsyncChild> actor = new mozilla::layout::VsyncChild(aDisplayIdentifier);
// There still has one ref-count after return, and it will be released in
// DeallocPVsyncChild().
return actor.forget().take();
}
bool
BackgroundChildImpl::DeallocPVsyncChild(PVsyncChild* aActor)
{
--- a/ipc/glue/BackgroundChildImpl.h
+++ b/ipc/glue/BackgroundChildImpl.h
@@ -83,17 +83,17 @@ protected:
virtual PCamerasChild*
AllocPCamerasChild() override;
virtual bool
DeallocPCamerasChild(PCamerasChild* aActor) override;
virtual PVsyncChild*
- AllocPVsyncChild() override;
+ AllocPVsyncChild(const nsID& aDisplayIdentifier) override;
virtual bool
DeallocPVsyncChild(PVsyncChild* aActor) override;
virtual PUDPSocketChild*
AllocPUDPSocketChild(const OptionalPrincipalInfo& aPrincipalInfo,
const nsCString& aFilter) override;
virtual bool
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -301,23 +301,23 @@ BackgroundParentImpl::RecvPNuwaConstruct
bool
BackgroundParentImpl::DeallocPNuwaParent(PNuwaParent *aActor)
{
return mozilla::dom::NuwaParent::Dealloc(aActor);
}
BackgroundParentImpl::PVsyncParent*
-BackgroundParentImpl::AllocPVsyncParent()
+BackgroundParentImpl::AllocPVsyncParent(const nsID& aDisplayIdentifier)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
RefPtr<mozilla::layout::VsyncParent> actor =
- mozilla::layout::VsyncParent::Create();
+ mozilla::layout::VsyncParent::Create(aDisplayIdentifier);
// There still has one ref-count after return, and it will be released in
// DeallocPVsyncParent().
return actor.forget().take();
}
bool
BackgroundParentImpl::DeallocPVsyncParent(PVsyncParent* aActor)
{
--- a/ipc/glue/BackgroundParentImpl.h
+++ b/ipc/glue/BackgroundParentImpl.h
@@ -75,17 +75,17 @@ protected:
AllocPFileDescriptorSetParent(const FileDescriptor& aFileDescriptor)
override;
virtual bool
DeallocPFileDescriptorSetParent(PFileDescriptorSetParent* aActor)
override;
virtual PVsyncParent*
- AllocPVsyncParent() override;
+ AllocPVsyncParent(const nsID& aDisplayIdentifier) override;
virtual bool
DeallocPVsyncParent(PVsyncParent* aActor) override;
virtual PBroadcastChannelParent*
AllocPBroadcastChannelParent(const PrincipalInfo& aPrincipalInfo,
const nsCString& aOrigin,
const nsString& aChannel,
--- a/ipc/glue/PBackground.ipdl
+++ b/ipc/glue/PBackground.ipdl
@@ -67,17 +67,19 @@ parent:
async PBackgroundIDBFactory(LoggingInfo loggingInfo);
async PBackgroundIndexedDBUtils();
// Use only for testing!
async FlushPendingFileDeletions();
- async PVsync();
+ // Create a PVsync for the given source ID. If you don't know which one you need,
+ // use mozilla::gfx::VsyncManager::kGlobalDisplaySourceID
+ async PVsync(nsID aSourceID);
async PCameras();
async PUDPSocket(OptionalPrincipalInfo pInfo, nsCString filter);
async PBroadcastChannel(PrincipalInfo pInfo, nsCString origin, nsString channel,
bool privateBrowsing);
async PServiceWorkerManager();
--- a/layout/ipc/PVsync.ipdl
+++ b/layout/ipc/PVsync.ipdl
@@ -18,24 +18,24 @@ namespace layout {
async protocol PVsync
{
manager PBackground;
child:
// Send vsync event from chrome to content process.
async Notify(TimeStamp aVsyncTimestamp) compress;
- // Send the vsync rate to the content process.
- async VsyncRate(float aVsyncRate);
+ // Send the vsync interval (time between vsyncs) to the content process.
+ async VsyncInterval(float aVsyncInterval);
parent:
// Content process use these messages to acquire the vsync event.
async Observe();
async Unobserve();
- async RequestVsyncRate();
+ async RequestVsyncInterval();
// This message is never sent. Each PVsync actor will stay alive as long as
// its PBackground manager.
async __delete__();
};
} // namespace layout
} // namespace mozilla
--- a/layout/ipc/VsyncChild.cpp
+++ b/layout/ipc/VsyncChild.cpp
@@ -1,94 +1,114 @@
/* -*- Mode: C++; tab-width: 2; 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/. */
#include "VsyncChild.h"
+#include "gfxVsync.h"
-#include "mozilla/VsyncDispatcher.h"
#include "nsThreadUtils.h"
+extern PRLogModuleInfo *gVsyncLog;
+#define VSYNC_LOG(...) MOZ_LOG(gVsyncLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
+
namespace mozilla {
namespace layout {
-VsyncChild::VsyncChild()
- : mObservingVsync(false)
+VsyncChild::VsyncChild(const nsID& aDisplayIdentifier)
+ : VsyncSource(aDisplayIdentifier)
+ , mObservingVsync(false)
, mIsShutdown(false)
- , mVsyncRate(TimeDuration::Forever())
+ , mVsyncInterval(TimeDuration::Forever())
{
+ char idstr[NSID_LENGTH];
+ mID.ToProvidedString(idstr);
+ VSYNC_LOG("[%s]: VsyncChild %p created for display ID %s\n", XRE_GetProcessTypeString(), this, idstr);
+
MOZ_ASSERT(NS_IsMainThread());
}
VsyncChild::~VsyncChild()
{
+ VSYNC_LOG("[%s]: VsyncChild %p destroyed\n", XRE_GetProcessTypeString(), this);
MOZ_ASSERT(NS_IsMainThread());
}
+void
+VsyncChild::EnableVsync()
+{
+ SendObserve();
+}
+
+void
+VsyncChild::DisableVsync()
+{
+ SendUnobserve();
+}
+
bool
VsyncChild::SendObserve()
{
MOZ_ASSERT(NS_IsMainThread());
+ VSYNC_LOG("[%s]: VsyncChild %p observing\n", XRE_GetProcessTypeString(), this);
if (!mObservingVsync && !mIsShutdown) {
mObservingVsync = true;
PVsyncChild::SendObserve();
}
return true;
}
bool
VsyncChild::SendUnobserve()
{
MOZ_ASSERT(NS_IsMainThread());
+ VSYNC_LOG("[%s]: VsyncChild %p unobserving\n", XRE_GetProcessTypeString(), this);
if (mObservingVsync && !mIsShutdown) {
mObservingVsync = false;
PVsyncChild::SendUnobserve();
}
return true;
}
void
VsyncChild::ActorDestroy(ActorDestroyReason aActorDestroyReason)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mIsShutdown);
mIsShutdown = true;
- mObserver = nullptr;
+
+ // clear up the VsyncSource's observers
+ Shutdown();
+
+ VSYNC_LOG("[%s]: VsyncChild %p actor destroyed\n", XRE_GetProcessTypeString(), this);
}
bool
VsyncChild::RecvNotify(const TimeStamp& aVsyncTimestamp)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mIsShutdown);
- if (mObservingVsync && mObserver) {
- mObserver->NotifyVsync(aVsyncTimestamp);
+ if (mObservingVsync) {
+ OnVsync(aVsyncTimestamp);
}
return true;
}
-void
-VsyncChild::SetVsyncObserver(VsyncObserver* aVsyncObserver)
+TimeDuration
+VsyncChild::GetVsyncInterval()
{
- MOZ_ASSERT(NS_IsMainThread());
- mObserver = aVsyncObserver;
-}
-
-TimeDuration
-VsyncChild::GetVsyncRate()
-{
- if (mVsyncRate == TimeDuration::Forever()) {
- PVsyncChild::SendRequestVsyncRate();
+ if (mVsyncInterval == TimeDuration::Forever()) {
+ PVsyncChild::SendRequestVsyncInterval();
}
- return mVsyncRate;
+ return mVsyncInterval;
}
bool
-VsyncChild::RecvVsyncRate(const float& aVsyncRate)
+VsyncChild::RecvVsyncInterval(const float& aVsyncInterval)
{
- mVsyncRate = TimeDuration::FromMilliseconds(aVsyncRate);
+ mVsyncInterval = TimeDuration::FromMilliseconds(aVsyncInterval);
return true;
}
} // namespace layout
} // namespace mozilla
--- a/layout/ipc/VsyncChild.h
+++ b/layout/ipc/VsyncChild.h
@@ -4,59 +4,63 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_layout_ipc_VsyncChild_h
#define mozilla_layout_ipc_VsyncChild_h
#include "mozilla/layout/PVsyncChild.h"
#include "nsISupportsImpl.h"
#include "mozilla/RefPtr.h"
+#include "gfxVsync.h"
namespace mozilla {
-
-class VsyncObserver;
-
namespace ipc {
class BackgroundChildImpl;
} // namespace ipc
namespace layout {
// 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
// thread only. The actor will stay alive until the process dies or its
// PVsyncParent actor dies.
-class VsyncChild final : public PVsyncChild
+class VsyncChild final :
+ public PVsyncChild,
+ public gfx::VsyncSource
{
- NS_INLINE_DECL_REFCOUNTING(VsyncChild)
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncChild, override)
friend class mozilla::ipc::BackgroundChildImpl;
public:
- // Hide the SendObserve/SendUnobserve in PVsyncChild. We add an flag
- // mObservingVsync to handle the race problem of unobserving vsync event.
+ // VsyncSource implementation
+ void EnableVsync() override;
+ void DisableVsync() override;
+ bool IsVsyncEnabled() override { return mObservingVsync; }
+
+ TimeDuration GetVsyncInterval() override;
+
+ const nsID& DisplayIdentifier() const { return mDisplayIdentifier; }
+
+private:
+ explicit VsyncChild(const nsID& aDisplayIdentifier);
+ virtual ~VsyncChild();
+
+ // Notify the other end whether we want to receive vsync events. We
+ // add an flag mObservingVsync to handle the race problem of
+ // unobserving vsync event.
bool SendObserve();
bool SendUnobserve();
- // Bind a VsyncObserver into VsyncChild after ipc channel connected.
- void SetVsyncObserver(VsyncObserver* aVsyncObserver);
- TimeDuration GetVsyncRate();
-
-private:
- VsyncChild();
- virtual ~VsyncChild();
-
virtual bool RecvNotify(const TimeStamp& aVsyncTimestamp) override;
- virtual bool RecvVsyncRate(const float& aVsyncRate) override;
+ virtual bool RecvVsyncInterval(const float& aVsyncInterval) override;
virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
+ nsID mDisplayIdentifier;
bool mObservingVsync;
bool mIsShutdown;
-
- // The content side vsync observer.
- RefPtr<VsyncObserver> mObserver;
- TimeDuration mVsyncRate;
+ TimeDuration mVsyncInterval;
};
} // namespace layout
} // namespace mozilla
#endif // mozilla_layout_ipc_VsyncChild_h
--- a/layout/ipc/VsyncParent.cpp
+++ b/layout/ipc/VsyncParent.cpp
@@ -6,31 +6,30 @@
#include "VsyncParent.h"
#include "BackgroundParent.h"
#include "BackgroundParentImpl.h"
#include "gfxPlatform.h"
#include "mozilla/unused.h"
#include "nsIThread.h"
#include "nsThreadUtils.h"
-#include "VsyncSource.h"
+#include "gfxVsync.h"
namespace mozilla {
using namespace ipc;
namespace layout {
/*static*/ already_AddRefed<VsyncParent>
-VsyncParent::Create()
+VsyncParent::Create(const nsID& aSourceID)
{
AssertIsOnBackgroundThread();
- RefPtr<gfx::VsyncSource> vsyncSource = gfxPlatform::GetPlatform()->GetHardwareVsync();
RefPtr<VsyncParent> vsyncParent = new VsyncParent();
- vsyncParent->mVsyncDispatcher = vsyncSource->GetRefreshTimerVsyncDispatcher();
+ vsyncParent->mSourceID = aSourceID;
return vsyncParent.forget();
}
VsyncParent::VsyncParent()
: mObservingVsync(false)
, mDestroyed(false)
, mBackgroundThread(NS_GetCurrentThread())
{
@@ -39,27 +38,29 @@ VsyncParent::VsyncParent()
}
VsyncParent::~VsyncParent()
{
// Since we use NS_INLINE_DECL_THREADSAFE_REFCOUNTING, we can't make sure
// VsyncParent is always released on the background thread.
}
-bool
+void
VsyncParent::NotifyVsync(TimeStamp aTimeStamp)
{
// Called on hardware vsync thread. We should post to current ipc thread.
MOZ_ASSERT(!IsOnBackgroundThread());
+
nsCOMPtr<nsIRunnable> vsyncEvent =
NS_NewRunnableMethodWithArg<TimeStamp>(this,
&VsyncParent::DispatchVsyncEvent,
aTimeStamp);
- MOZ_ALWAYS_SUCCEEDS(mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL));
- return true;
+ // This dispatch might fail, if we're in the middle of shutting down when
+ // a vsync comes in. Ignore that failure.
+ Unused << mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL);
}
void
VsyncParent::DispatchVsyncEvent(TimeStamp aTimeStamp)
{
AssertIsOnBackgroundThread();
// If we call NotifyVsync() when we handle ActorDestroy() message, we might
@@ -68,54 +69,56 @@ VsyncParent::DispatchVsyncEvent(TimeStam
// NotifyVsync(). We use mObservingVsync and mDestroyed flags to skip this
// notification.
if (mObservingVsync && !mDestroyed) {
Unused << SendNotify(aTimeStamp);
}
}
bool
-VsyncParent::RecvRequestVsyncRate()
+VsyncParent::RecvRequestVsyncInterval()
{
AssertIsOnBackgroundThread();
- TimeDuration vsyncRate = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay().GetVsyncRate();
- Unused << SendVsyncRate(vsyncRate.ToMilliseconds());
+ RefPtr<gfx::VsyncSource> source = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetSource(mSourceID);
+ Unused << SendVsyncInterval(source->GetVsyncInterval().ToMilliseconds());
return true;
}
bool
VsyncParent::RecvObserve()
{
AssertIsOnBackgroundThread();
if (!mObservingVsync) {
- mVsyncDispatcher->AddChildRefreshTimer(this);
+ RefPtr<gfx::VsyncSource> source = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetSource(mSourceID);
+ source->AddVsyncObserver(this);
mObservingVsync = true;
return true;
}
return false;
}
bool
VsyncParent::RecvUnobserve()
{
AssertIsOnBackgroundThread();
if (mObservingVsync) {
- mVsyncDispatcher->RemoveChildRefreshTimer(this);
+ MOZ_ASSERT(AttachedSource(), "RecvUnobserve, but we don't seem to have a source attached?");
+ AttachedSource()->RemoveVsyncObserver(this);
mObservingVsync = false;
return true;
}
return false;
}
void
VsyncParent::ActorDestroy(ActorDestroyReason aReason)
{
MOZ_ASSERT(!mDestroyed);
AssertIsOnBackgroundThread();
- if (mObservingVsync) {
- mVsyncDispatcher->RemoveChildRefreshTimer(this);
+ if (mObservingVsync && AttachedSource()) {
+ AttachedSource()->RemoveVsyncObserver(this);
+ mObservingVsync = false;
}
- mVsyncDispatcher = nullptr;
mDestroyed = true;
}
} // namespace layout
} // namespace mozilla
--- a/layout/ipc/VsyncParent.h
+++ b/layout/ipc/VsyncParent.h
@@ -2,55 +2,61 @@
/* 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/. */
#ifndef mozilla_layout_ipc_VsyncParent_h
#define mozilla_layout_ipc_VsyncParent_h
#include "mozilla/layout/PVsyncParent.h"
-#include "mozilla/VsyncDispatcher.h"
#include "nsCOMPtr.h"
#include "mozilla/RefPtr.h"
+#include "gfxVsync.h"
class nsIThread;
namespace mozilla {
+namespace gfx {
+class VsyncManager;
+class VsyncSource;
+} // namespace gfx
+
namespace ipc {
class BackgroundParentImpl;
} // namespace ipc
namespace layout {
// 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
+ public gfx::VsyncObserver
{
friend class mozilla::ipc::BackgroundParentImpl;
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncParent, override)
private:
- static already_AddRefed<VsyncParent> Create();
+ static already_AddRefed<VsyncParent> Create(const nsID& aSourceID);
VsyncParent();
virtual ~VsyncParent();
- virtual bool NotifyVsync(TimeStamp aTimeStamp) override;
- virtual bool RecvRequestVsyncRate() override;
+ virtual void NotifyVsync(TimeStamp aTimeStamp) override;
+ virtual bool RecvRequestVsyncInterval() override;
virtual bool RecvObserve() override;
virtual bool RecvUnobserve() override;
virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
void DispatchVsyncEvent(TimeStamp aTimeStamp);
bool mObservingVsync;
bool mDestroyed;
nsCOMPtr<nsIThread> mBackgroundThread;
- RefPtr<RefreshTimerVsyncDispatcher> mVsyncDispatcher;
+ nsID mSourceID;
};
} // namespace layout
} // namespace mozilla
#endif //mozilla_layout_ipc_VsyncParent_h