Bug 1048667. Small vsync framework. r=roc

This commit is contained in:
Mason Chang 2014-10-23 18:50:31 -07:00
parent a689009ad0
commit 4a7e5a8c86
5 changed files with 85 additions and 6 deletions

View File

@ -97,7 +97,6 @@ private:
class CompositorVsyncObserver MOZ_FINAL : public VsyncObserver
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorVsyncObserver)
friend class CompositorParent;
public:

View File

@ -6,6 +6,11 @@
#include "VsyncDispatcher.h"
#include "mozilla/ClearOnShutdown.h"
#include "CompositorParent.h"
#include "gfxPrefs.h"
#ifdef MOZ_WIDGET_GONK
#include "GeckoTouchDispatcher.h"
#endif
using namespace mozilla::layers;
@ -25,24 +30,71 @@ VsyncDispatcher::GetInstance()
}
VsyncDispatcher::VsyncDispatcher()
: mCompositorObserverLock("CompositorObserverLock")
{
}
VsyncDispatcher::~VsyncDispatcher()
{
MutexAutoLock lock(mCompositorObserverLock);
mCompositorObservers.Clear();
}
void
VsyncDispatcher::DispatchTouchEvents(bool aNotifiedCompositors, nsecs_t aAndroidVsyncTime)
{
// 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(aAndroidVsyncTime);
}
#endif
}
void
VsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp, nsecs_t aAndroidVsyncTime)
{
bool notifiedCompositors = false;
if (gfxPrefs::VsyncAlignedCompositor()) {
MutexAutoLock lock(mCompositorObserverLock);
notifiedCompositors = NotifyVsyncObservers(aVsyncTimestamp, mCompositorObservers);
}
DispatchTouchEvents(notifiedCompositors, aAndroidVsyncTime);
}
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)
{
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
MutexAutoLock lock(mCompositorObserverLock);
if (!mCompositorObservers.Contains(aVsyncObserver)) {
mCompositorObservers.AppendElement(aVsyncObserver);
}
}
void
VsyncDispatcher::RemoveCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
{
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
MutexAutoLock lock(mCompositorObserverLock);
if (mCompositorObservers.Contains(aVsyncObserver)) {
mCompositorObservers.RemoveElement(aVsyncObserver);
} else {
NS_WARNING("Could not delete a compositor vsync observer\n");
}
}
} // namespace mozilla

View File

@ -6,20 +6,36 @@
#ifndef mozilla_widget_VsyncDispatcher_h
#define mozilla_widget_VsyncDispatcher_h
#include "base/message_loop.h"
#include "mozilla/Mutex.h"
#include "nsISupportsImpl.h"
#include "nsTArray.h"
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
typedef int64_t nsecs_t; // nano-seconds
class MessageLoop;
namespace mozilla {
class TimeStamp;
namespace layers {
class CompositorVsyncObserver;
}
class VsyncObserver
{
// Must be destroyed on main thread since the compositor is as well
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(VsyncObserver)
public:
// The method called when a vsync occurs. Return true if some work was done.
// Vsync notifications will occur on the hardware vsync thread
virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) = 0;
protected:
virtual ~VsyncObserver() { }
VsyncObserver() {}
virtual ~VsyncObserver() {}
};
// VsyncDispatcher is used to dispatch vsync events to the registered observers.
@ -29,6 +45,8 @@ class VsyncDispatcher
public:
static VsyncDispatcher* GetInstance();
// Called on the vsync thread when a hardware vsync occurs
void NotifyVsync(TimeStamp aVsyncTimestamp, nsecs_t aAndroidVsyncTime);
// Compositor vsync observers must be added/removed on the compositor thread
void AddCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
@ -37,6 +55,14 @@ public:
private:
VsyncDispatcher();
virtual ~VsyncDispatcher();
void DispatchTouchEvents(bool aNotifiedCompositors, nsecs_t aAndroidVSyncTime);
// 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;
};
} // namespace mozilla

View File

@ -240,15 +240,16 @@ HwcComposer2D::RunVsyncEventControl(bool aEnable)
void
HwcComposer2D::Vsync(int aDisplay, nsecs_t aVsyncTimestamp)
{
nsecs_t timeSinceInit = aVsyncTimestamp - sAndroidInitTime;
TimeStamp vsyncTime = sMozInitTime + TimeDuration::FromMicroseconds(timeSinceInit / 1000);
#ifdef MOZ_ENABLE_PROFILER_SPS
if (profiler_is_active()) {
nsecs_t timeSinceInit = aVsyncTimestamp - sAndroidInitTime;
TimeStamp vsyncTime = sMozInitTime + TimeDuration::FromMicroseconds(timeSinceInit / 1000);
CompositorParent::PostInsertVsyncProfilerMarker(vsyncTime);
CompositorParent::PostInsertVsyncProfilerMarker(vsyncTime);
}
#endif
GeckoTouchDispatcher::NotifyVsync(aVsyncTimestamp);
VsyncDispatcher::GetInstance()->NotifyVsync(vsyncTime, aVsyncTimestamp);
}
// Called on the "invalidator" thread (run from HAL).

View File

@ -15,6 +15,7 @@
# limitations under the License.
EXPORTS += [
'GeckoTouchDispatcher.h',
'GonkPermission.h',
'OrientationObserver.h',
]