Bug 1101974. Part 5 - Refactor VsyncDispatcher to use VsyncSource. r=kats

This commit is contained in:
Mason Chang 2014-12-18 08:30:06 -08:00
parent 5f06caa746
commit af4d0097b2
2 changed files with 25 additions and 92 deletions

View File

@ -7,6 +7,8 @@
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/layers/CompositorParent.h"
#include "gfxPrefs.h"
#include "gfxPlatform.h"
#include "VsyncSource.h"
#ifdef MOZ_ENABLE_PROFILER_SPS
#include "GeckoProfiler.h"
@ -21,97 +23,51 @@ using namespace mozilla::layers;
namespace mozilla {
StaticRefPtr<VsyncDispatcher> sVsyncDispatcher;
/*static*/ VsyncDispatcher*
VsyncDispatcher::GetInstance()
{
if (!sVsyncDispatcher) {
sVsyncDispatcher = new VsyncDispatcher();
ClearOnShutdown(&sVsyncDispatcher);
}
return sVsyncDispatcher;
}
VsyncDispatcher::VsyncDispatcher()
: mCompositorObserverLock("CompositorObserverLock")
{
MOZ_ASSERT(XRE_IsParentProcess());
gfxPlatform::GetPlatform()->GetHardwareVsync()->AddVsyncDispatcher(this);
}
VsyncDispatcher::~VsyncDispatcher()
{
MutexAutoLock lock(mCompositorObserverLock);
mCompositorObservers.Clear();
}
void
VsyncDispatcher::SetVsyncSource(VsyncSource* aVsyncSource)
{
mVsyncSource = aVsyncSource;
}
void
VsyncDispatcher::DispatchTouchEvents(bool aNotifiedCompositors, TimeStamp aVsyncTime)
{
// Touch events can sometimes start a composite, so make sure we dispatch touches
// even if we don't composite
#ifdef MOZ_WIDGET_GONK
if (!aNotifiedCompositors && gfxPrefs::TouchResampling()) {
GeckoTouchDispatcher::NotifyVsync(aVsyncTime);
}
#endif
// We auto remove this vsync dispatcher from the vsync source in the nsBaseWidget
MOZ_ASSERT(NS_IsMainThread());
}
void
VsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
{
bool notifiedCompositors = false;
// In hardware vsync thread
#ifdef MOZ_ENABLE_PROFILER_SPS
if (profiler_is_active()) {
CompositorParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
}
#endif
if (gfxPrefs::VsyncAlignedCompositor()) {
MutexAutoLock lock(mCompositorObserverLock);
notifiedCompositors = NotifyVsyncObservers(aVsyncTimestamp, mCompositorObservers);
if (gfxPrefs::VsyncAlignedCompositor() && mCompositorVsyncObserver) {
mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
}
DispatchTouchEvents(notifiedCompositors, aVsyncTimestamp);
}
bool
VsyncDispatcher::NotifyVsyncObservers(TimeStamp aVsyncTimestamp, nsTArray<nsRefPtr<VsyncObserver>>& aObservers)
{
// Callers should lock the respective lock for the aObservers before calling this function
for (size_t i = 0; i < aObservers.Length(); i++) {
aObservers[i]->NotifyVsync(aVsyncTimestamp);
}
return !aObservers.IsEmpty();
}
void
VsyncDispatcher::AddCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
VsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
{
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
MutexAutoLock lock(mCompositorObserverLock);
if (!mCompositorObservers.Contains(aVsyncObserver)) {
mCompositorObservers.AppendElement(aVsyncObserver);
}
mCompositorVsyncObserver = aVsyncObserver;
}
void
VsyncDispatcher::RemoveCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
VsyncDispatcher::Shutdown()
{
MOZ_ASSERT(CompositorParent::IsInCompositorThread() || NS_IsMainThread());
MutexAutoLock lock(mCompositorObserverLock);
if (mCompositorObservers.Contains(aVsyncObserver)) {
mCompositorObservers.RemoveElement(aVsyncObserver);
} else {
NS_WARNING("Could not delete a compositor vsync observer\n");
}
// Need to explicitly remove VsyncDispatcher when the nsBaseWidget shuts down.
// Otherwise, we would get dead vsync notifications between when the nsBaseWidget
// shuts down and the CompositorParent shuts down.
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveVsyncDispatcher(this);
}
} // namespace mozilla

View File

@ -12,8 +12,6 @@
#include "nsTArray.h"
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
class MessageLoop;
namespace mozilla {
class TimeStamp;
@ -21,23 +19,10 @@ namespace layers {
class CompositorVsyncObserver;
}
// Controls how and when to enable/disable vsync.
class VsyncSource
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncSource)
virtual void EnableVsync() = 0;
virtual void DisableVsync() = 0;
virtual bool IsVsyncEnabled() = 0;
protected:
virtual ~VsyncSource() {}
}; // VsyncSource
class VsyncObserver
{
// Must be destroyed on main thread since the compositor is as well
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(VsyncObserver)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncObserver)
public:
// The method called when a vsync occurs. Return true if some work was done.
@ -55,7 +40,8 @@ class VsyncDispatcher
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncDispatcher)
public:
static VsyncDispatcher* GetInstance();
VsyncDispatcher();
// Called on the vsync thread when a hardware vsync occurs
// The aVsyncTimestamp can mean different things depending on the platform:
// b2g - The vsync timestamp of the previous frame that was just displayed
@ -63,24 +49,15 @@ public:
// TODO: Windows / Linux. DOCUMENT THIS WHEN IMPLEMENTING ON THOSE PLATFORMS
// Android: TODO
void NotifyVsync(TimeStamp aVsyncTimestamp);
void SetVsyncSource(VsyncSource* aVsyncSource);
// Compositor vsync observers must be added/removed on the compositor thread
void AddCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
void RemoveCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
void Shutdown();
private:
VsyncDispatcher();
virtual ~VsyncDispatcher();
void DispatchTouchEvents(bool aNotifiedCompositors, TimeStamp aVsyncTime);
// Called on the vsync thread. Returns true if observers were notified
bool NotifyVsyncObservers(TimeStamp aVsyncTimestamp, nsTArray<nsRefPtr<VsyncObserver>>& aObservers);
// Can have multiple compositors. On desktop, this is 1 compositor per window
Mutex mCompositorObserverLock;
nsTArray<nsRefPtr<VsyncObserver>> mCompositorObservers;
nsRefPtr<VsyncSource> mVsyncSource;
nsRefPtr<VsyncObserver> mCompositorVsyncObserver;
}; // VsyncDispatcher
} // namespace mozilla