Bug 1095242. Part 4: Unobserve vsync in CompositorVsyncDispatcher. r=kats

This commit is contained in:
Mason Chang 2015-01-20 08:31:24 -08:00
parent 9093be777c
commit ebe0a9bec5
4 changed files with 80 additions and 8 deletions

View File

@ -41,6 +41,7 @@ VsyncSource::GetRefreshTimerVsyncDispatcher()
VsyncSource::Display::Display()
: mDispatcherLock("display dispatcher lock")
, mRefreshTimerNeedsVsync(false)
{
MOZ_ASSERT(NS_IsMainThread());
mRefreshTimerVsyncDispatcher = new RefreshTimerVsyncDispatcher();
@ -72,10 +73,13 @@ VsyncSource::Display::AddCompositorVsyncDispatcher(CompositorVsyncDispatcher* aC
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aCompositorVsyncDispatcher);
MutexAutoLock lock(mDispatcherLock);
if (!mCompositorVsyncDispatchers.Contains(aCompositorVsyncDispatcher)) {
mCompositorVsyncDispatchers.AppendElement(aCompositorVsyncDispatcher);
{ // scope lock
MutexAutoLock lock(mDispatcherLock);
if (!mCompositorVsyncDispatchers.Contains(aCompositorVsyncDispatcher)) {
mCompositorVsyncDispatchers.AppendElement(aCompositorVsyncDispatcher);
}
}
UpdateVsyncStatus();
}
void
@ -83,8 +87,43 @@ VsyncSource::Display::RemoveCompositorVsyncDispatcher(CompositorVsyncDispatcher*
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aCompositorVsyncDispatcher);
MutexAutoLock lock(mDispatcherLock);
mCompositorVsyncDispatchers.RemoveElement(aCompositorVsyncDispatcher);
{ // Scope lock
MutexAutoLock lock(mDispatcherLock);
if (mCompositorVsyncDispatchers.Contains(aCompositorVsyncDispatcher)) {
mCompositorVsyncDispatchers.RemoveElement(aCompositorVsyncDispatcher);
}
}
UpdateVsyncStatus();
}
void
VsyncSource::Display::NotifyRefreshTimerVsyncStatus(bool aEnable)
{
MOZ_ASSERT(NS_IsMainThread());
mRefreshTimerNeedsVsync = aEnable;
UpdateVsyncStatus();
}
void
VsyncSource::Display::UpdateVsyncStatus()
{
MOZ_ASSERT(NS_IsMainThread());
// WARNING: This function SHOULD NOT BE CALLED WHILE HOLDING LOCKS
// NotifyVsync grabs a lock to dispatch vsync events
// When disabling vsync, we wait for the underlying thread to stop on some platforms
// We can deadlock if we wait for the underlying vsync thread to stop
// while the vsync thread is in NotifyVsync.
bool enableVsync = false;
{ // scope lock
MutexAutoLock lock(mDispatcherLock);
enableVsync = !mCompositorVsyncDispatchers.IsEmpty() || mRefreshTimerNeedsVsync;
}
if (enableVsync) {
EnableVsync();
} else {
DisableVsync();
}
}
nsRefPtr<RefreshTimerVsyncDispatcher>

View File

@ -49,6 +49,7 @@ public:
void AddCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher);
void RemoveCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher);
void NotifyRefreshTimerVsyncStatus(bool aEnable);
// These should all only be called on the main thread
virtual void EnableVsync() = 0;
@ -56,7 +57,10 @@ public:
virtual bool IsVsyncEnabled() = 0;
private:
void UpdateVsyncStatus();
Mutex mDispatcherLock;
bool mRefreshTimerNeedsVsync;
nsTArray<nsRefPtr<CompositorVsyncDispatcher>> mCompositorVsyncDispatchers;
nsRefPtr<RefreshTimerVsyncDispatcher> mRefreshTimerVsyncDispatcher;
};

View File

@ -18,10 +18,10 @@ namespace mozilla {
CompositorVsyncDispatcher::CompositorVsyncDispatcher()
: mCompositorObserverLock("CompositorObserverLock")
, mDidShutdown(false)
{
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
}
CompositorVsyncDispatcher::~CompositorVsyncDispatcher()
@ -34,7 +34,7 @@ CompositorVsyncDispatcher::~CompositorVsyncDispatcher()
void
CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
{
// In hardware vsync thread
// In vsync thread
#ifdef MOZ_ENABLE_PROFILER_SPS
if (profiler_is_active()) {
layers::CompositorParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
@ -47,12 +47,34 @@ CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
}
}
void
CompositorVsyncDispatcher::ObserveVsync(bool aEnable)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess());
if (mDidShutdown) {
return;
}
if (aEnable) {
gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
} else {
gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveCompositorVsyncDispatcher(this);
}
}
void
CompositorVsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
{
MOZ_ASSERT(layers::CompositorParent::IsInCompositorThread());
MutexAutoLock lock(mCompositorObserverLock);
mCompositorVsyncObserver = aVsyncObserver;
bool observeVsync = aVsyncObserver != nullptr;
nsCOMPtr<nsIRunnable> vsyncControl = NS_NewRunnableMethodWithArg<bool>(this,
&CompositorVsyncDispatcher::ObserveVsync,
observeVsync);
NS_DispatchToMainThread(vsyncControl);
}
void
@ -63,7 +85,12 @@ CompositorVsyncDispatcher::Shutdown()
// shuts down and the CompositorParent shuts down.
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveCompositorVsyncDispatcher(this);
ObserveVsync(false);
mDidShutdown = true;
{ // scope lock
MutexAutoLock lock(mCompositorObserverLock);
mCompositorVsyncObserver = nullptr;
}
}
RefreshTimerVsyncDispatcher::RefreshTimerVsyncDispatcher()

View File

@ -48,9 +48,11 @@ public:
private:
virtual ~CompositorVsyncDispatcher();
void ObserveVsync(bool aEnable);
Mutex mCompositorObserverLock;
nsRefPtr<VsyncObserver> mCompositorVsyncObserver;
bool mDidShutdown;
};
// Dispatch vsync event to ipc actor parent and chrome RefreshTimer.