gecko-dev/widget/VsyncDispatcher.cpp
Kan-Ru Chen 53ad814f85 Bug 1194751 - Part 4. Add ScreenManager and Screen classes. r=jimm,karlt,mconley
ScreenManager takes the common parts of ScreenManagerWin,
ScreenManagerGtk and ScreenManagerCocoa. It caches all screen
information in the new Screen class. The cache are updated when the OS
notifies there is a monitor config change; all changes will be pushed to
content processes via PContent (patch part 6.)

Screen is a pure data object. All platform dependent logic will be in
widget specific helper classes.

Each process will have a singleton ScreenManager object. Widget
specific helper object is held alive by the ScreenManager when
necessary, for example to receive updates from the OS.

The change to to VsyncDispatcher.cpp is due to unified-build bustage.

ScreenManager::ScreenForNativeWidget is not implemented because it
will be removed in patch part 6.

MozReview-Commit-ID: 5ezytAXSqHp
***
fixup

MozReview-Commit-ID: DQtq3UVZytA

--HG--
extra : rebase_source : c1a5aac713de783586e93109fe3e197ffdc1a3ca
2017-03-14 18:44:54 +08:00

190 lines
5.2 KiB
C++

/* -*- 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 "MainThreadUtils.h"
#include "VsyncDispatcher.h"
#include "VsyncSource.h"
#include "gfxPlatform.h"
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorThread.h"
#ifdef MOZ_GECKO_PROFILER
#include "GeckoProfiler.h"
#include "ProfilerMarkers.h"
#endif
using namespace mozilla::layers;
namespace mozilla {
CompositorVsyncDispatcher::CompositorVsyncDispatcher()
: mCompositorObserverLock("CompositorObserverLock")
, mDidShutdown(false)
{
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
}
CompositorVsyncDispatcher::~CompositorVsyncDispatcher()
{
MOZ_ASSERT(XRE_IsParentProcess());
// We auto remove this vsync dispatcher from the vsync source in the nsBaseWidget
}
void
CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
{
// In vsync thread
#ifdef MOZ_GECKO_PROFILER
layers::CompositorBridgeParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
#endif
MutexAutoLock lock(mCompositorObserverLock);
if (mCompositorVsyncObserver) {
mCompositorVsyncObserver->NotifyVsync(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)
{
// When remote compositing or running gtests, vsync observation is
// initiated on the main thread. Otherwise, it is initiated from the compositor
// thread.
MOZ_ASSERT(NS_IsMainThread() || CompositorThreadHolder::IsInCompositorThread());
{ // scope lock
MutexAutoLock lock(mCompositorObserverLock);
mCompositorVsyncObserver = aVsyncObserver;
}
bool observeVsync = aVsyncObserver != nullptr;
nsCOMPtr<nsIRunnable> vsyncControl = NewRunnableMethod<bool>(this,
&CompositorVsyncDispatcher::ObserveVsync,
observeVsync);
NS_DispatchToMainThread(vsyncControl);
}
void
CompositorVsyncDispatcher::Shutdown()
{
// Need to explicitly remove CompositorVsyncDispatcher when the nsBaseWidget shuts down.
// Otherwise, we would get dead vsync notifications between when the nsBaseWidget
// shuts down and the CompositorBridgeParent shuts down.
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
ObserveVsync(false);
mDidShutdown = true;
{ // scope lock
MutexAutoLock lock(mCompositorObserverLock);
mCompositorVsyncObserver = nullptr;
}
}
RefreshTimerVsyncDispatcher::RefreshTimerVsyncDispatcher()
: mRefreshTimersLock("RefreshTimers lock")
{
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
}
RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher()
{
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
}
void
RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
{
MutexAutoLock lock(mRefreshTimersLock);
for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
mChildRefreshTimers[i]->NotifyVsync(aVsyncTimestamp);
}
if (mParentRefreshTimer) {
mParentRefreshTimer->NotifyVsync(aVsyncTimestamp);
}
}
void
RefreshTimerVsyncDispatcher::SetParentRefreshTimer(VsyncObserver* aVsyncObserver)
{
MOZ_ASSERT(NS_IsMainThread());
{ // lock scope because UpdateVsyncStatus runs on main thread and will deadlock
MutexAutoLock lock(mRefreshTimersLock);
mParentRefreshTimer = aVsyncObserver;
}
UpdateVsyncStatus();
}
void
RefreshTimerVsyncDispatcher::AddChildRefreshTimer(VsyncObserver* aVsyncObserver)
{
{ // scope lock - called on pbackground thread
MutexAutoLock lock(mRefreshTimersLock);
MOZ_ASSERT(aVsyncObserver);
if (!mChildRefreshTimers.Contains(aVsyncObserver)) {
mChildRefreshTimers.AppendElement(aVsyncObserver);
}
}
UpdateVsyncStatus();
}
void
RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver)
{
{ // scope lock - called on pbackground thread
MutexAutoLock lock(mRefreshTimersLock);
MOZ_ASSERT(aVsyncObserver);
mChildRefreshTimers.RemoveElement(aVsyncObserver);
}
UpdateVsyncStatus();
}
void
RefreshTimerVsyncDispatcher::UpdateVsyncStatus()
{
if (!NS_IsMainThread()) {
NS_DispatchToMainThread(NewRunnableMethod(this,
&RefreshTimerVsyncDispatcher::UpdateVsyncStatus));
return;
}
gfx::VsyncSource::Display& display = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
display.NotifyRefreshTimerVsyncStatus(NeedsVsync());
}
bool
RefreshTimerVsyncDispatcher::NeedsVsync()
{
MOZ_ASSERT(NS_IsMainThread());
MutexAutoLock lock(mRefreshTimersLock);
return (mParentRefreshTimer != nullptr) || !mChildRefreshTimers.IsEmpty();
}
} // namespace mozilla