Skip to content

Commit

Permalink
Bug 1101974. Part 5 - Refactor VsyncDispatcher to use VsyncSource. r=…
Browse files Browse the repository at this point in the history
…kats
  • Loading branch information
Mason Chang committed Dec 18, 2014
1 parent ab9e349 commit 62b7fe5
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 92 deletions.
82 changes: 19 additions & 63 deletions widget/VsyncDispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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);
MutexAutoLock lock(mCompositorObserverLock);
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
35 changes: 6 additions & 29 deletions widget/VsyncDispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,17 @@
#include "nsTArray.h"
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"

class MessageLoop;

namespace mozilla {
class TimeStamp;

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.
Expand All @@ -55,32 +40,24 @@ 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
// OSX - The vsync timestamp of the upcoming frame
// 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
Expand Down

0 comments on commit 62b7fe5

Please sign in to comment.