bug 552020 Part 1: Hook into CVDisplayLink to get vsync events on OSX. r=benwa,mstange
This commit is contained in:
@@ -460,6 +460,10 @@ gfxPlatform::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
|
RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
|
||||||
|
|
||||||
|
if (gfxPrefs::HardwareVsyncEnabled() && gfxPrefs::VsyncAlignedCompositor()) {
|
||||||
|
gPlatform->InitHardwareVsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sLayersIPCIsUp = false;
|
static bool sLayersIPCIsUp = false;
|
||||||
|
|||||||
@@ -590,6 +590,11 @@ protected:
|
|||||||
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen,
|
void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen,
|
||||||
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
|
eFontPrefLang aCharLang, eFontPrefLang aPageLang);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialized hardware vsync based on each platform.
|
||||||
|
*/
|
||||||
|
virtual void InitHardwareVsync() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method, creates a draw target for a specific Azure backend.
|
* Helper method, creates a draw target for a specific Azure backend.
|
||||||
* Used by CreateOffscreenDrawTarget.
|
* Used by CreateOffscreenDrawTarget.
|
||||||
|
|||||||
@@ -17,11 +17,13 @@
|
|||||||
|
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
|
#include "mozilla/VsyncDispatcher.h"
|
||||||
#include "qcms.h"
|
#include "qcms.h"
|
||||||
#include "gfx2DGlue.h"
|
#include "gfx2DGlue.h"
|
||||||
#include "gfxPrefs.h"
|
#include "gfxPrefs.h"
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <CoreVideo/CoreVideo.h>
|
||||||
|
|
||||||
#include "nsCocoaFeatures.h"
|
#include "nsCocoaFeatures.h"
|
||||||
|
|
||||||
@@ -419,6 +421,91 @@ gfxPlatformMac::UseProgressivePaint()
|
|||||||
return nsCocoaFeatures::OnLionOrLater() && gfxPlatform::UseProgressivePaint();
|
return nsCocoaFeatures::OnLionOrLater() && gfxPlatform::UseProgressivePaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is the renderer output callback function, called on the vsync thread
|
||||||
|
static CVReturn VsyncCallback(CVDisplayLinkRef aDisplayLink,
|
||||||
|
const CVTimeStamp* aNow,
|
||||||
|
const CVTimeStamp* aOutputTime,
|
||||||
|
CVOptionFlags aFlagsIn,
|
||||||
|
CVOptionFlags* aFlagsOut,
|
||||||
|
void* aDisplayLinkContext)
|
||||||
|
{
|
||||||
|
mozilla::VsyncSource* vsyncSource = (mozilla::VsyncSource*) aDisplayLinkContext;
|
||||||
|
if (vsyncSource->IsVsyncEnabled()) {
|
||||||
|
// Now refers to "Now" as in when this callback is called or when the current frame
|
||||||
|
// is displayed. aOutputTime is when the next frame should be displayed.
|
||||||
|
// Now is VERY VERY noisy, aOutputTime is in the future though.
|
||||||
|
int64_t timestamp = aOutputTime->hostTime;
|
||||||
|
mozilla::TimeStamp vsyncTime = mozilla::TimeStamp::FromSystemTime(timestamp);
|
||||||
|
mozilla::VsyncDispatcher::GetInstance()->NotifyVsync(vsyncTime);
|
||||||
|
return kCVReturnSuccess;
|
||||||
|
} else {
|
||||||
|
return kCVReturnDisplayLinkNotRunning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OSXVsyncSource MOZ_FINAL : public mozilla::VsyncSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OSXVsyncSource()
|
||||||
|
{
|
||||||
|
EnableVsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void EnableVsync() MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
// Create a display link capable of being used with all active displays
|
||||||
|
// TODO: See if we need to create an active DisplayLink for each monitor in multi-monitor
|
||||||
|
// situations. According to the docs, it is compatible with all displays running on the computer
|
||||||
|
// But if we have different monitors at different display rates, we may hit issues.
|
||||||
|
if (CVDisplayLinkCreateWithActiveCGDisplays(&mDisplayLink) != kCVReturnSuccess) {
|
||||||
|
NS_WARNING("Could not create a display link, returning");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the renderer output callback function
|
||||||
|
if (CVDisplayLinkSetOutputCallback(mDisplayLink, &VsyncCallback, this) != kCVReturnSuccess) {
|
||||||
|
NS_WARNING("Could not set displaylink output callback");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate the display link
|
||||||
|
if (CVDisplayLinkStart(mDisplayLink) != kCVReturnSuccess) {
|
||||||
|
NS_WARNING("Could not activate the display link");
|
||||||
|
mDisplayLink = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DisableVsync() MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
// Release the display link
|
||||||
|
if (mDisplayLink) {
|
||||||
|
CVDisplayLinkRelease(mDisplayLink);
|
||||||
|
mDisplayLink = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool IsVsyncEnabled() MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
return mDisplayLink != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual ~OSXVsyncSource()
|
||||||
|
{
|
||||||
|
DisableVsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manages the display link render thread
|
||||||
|
CVDisplayLinkRef mDisplayLink;
|
||||||
|
}; // OSXVsyncSource
|
||||||
|
|
||||||
|
void
|
||||||
|
gfxPlatformMac::InitHardwareVsync()
|
||||||
|
{
|
||||||
|
nsRefPtr<VsyncSource> osxVsyncSource = new OSXVsyncSource();
|
||||||
|
mozilla::VsyncDispatcher::GetInstance()->SetVsyncSource(osxVsyncSource);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gfxPlatformMac::GetPlatformCMSOutputProfile(void* &mem, size_t &size)
|
gfxPlatformMac::GetPlatformCMSOutputProfile(void* &mem, size_t &size)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ public:
|
|||||||
|
|
||||||
virtual bool UseTiling() MOZ_OVERRIDE;
|
virtual bool UseTiling() MOZ_OVERRIDE;
|
||||||
virtual bool UseProgressivePaint() MOZ_OVERRIDE;
|
virtual bool UseProgressivePaint() MOZ_OVERRIDE;
|
||||||
|
virtual void InitHardwareVsync() MOZ_OVERRIDE;
|
||||||
|
|
||||||
// lower threshold on font anti-aliasing
|
// lower threshold on font anti-aliasing
|
||||||
uint32_t GetAntiAliasingThreshold() { return mFontAntiAliasingThreshold; }
|
uint32_t GetAntiAliasingThreshold() { return mFontAntiAliasingThreshold; }
|
||||||
|
|||||||
@@ -41,6 +41,12 @@ VsyncDispatcher::~VsyncDispatcher()
|
|||||||
mCompositorObservers.Clear();
|
mCompositorObservers.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VsyncDispatcher::SetVsyncSource(VsyncSource* aVsyncSource)
|
||||||
|
{
|
||||||
|
mVsyncSource = aVsyncSource;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VsyncDispatcher::DispatchTouchEvents(bool aNotifiedCompositors, TimeStamp aVsyncTime)
|
VsyncDispatcher::DispatchTouchEvents(bool aNotifiedCompositors, TimeStamp aVsyncTime)
|
||||||
{
|
{
|
||||||
@@ -88,7 +94,7 @@ VsyncDispatcher::AddCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
|
|||||||
void
|
void
|
||||||
VsyncDispatcher::RemoveCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
|
VsyncDispatcher::RemoveCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
|
MOZ_ASSERT(CompositorParent::IsInCompositorThread() || NS_IsMainThread());
|
||||||
MutexAutoLock lock(mCompositorObserverLock);
|
MutexAutoLock lock(mCompositorObserverLock);
|
||||||
if (mCompositorObservers.Contains(aVsyncObserver)) {
|
if (mCompositorObservers.Contains(aVsyncObserver)) {
|
||||||
mCompositorObservers.RemoveElement(aVsyncObserver);
|
mCompositorObservers.RemoveElement(aVsyncObserver);
|
||||||
|
|||||||
@@ -21,6 +21,19 @@ namespace layers {
|
|||||||
class CompositorVsyncObserver;
|
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
|
class VsyncObserver
|
||||||
{
|
{
|
||||||
// Must be destroyed on main thread since the compositor is as well
|
// Must be destroyed on main thread since the compositor is as well
|
||||||
@@ -34,7 +47,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
VsyncObserver() {}
|
VsyncObserver() {}
|
||||||
virtual ~VsyncObserver() {}
|
virtual ~VsyncObserver() {}
|
||||||
};
|
}; // VsyncObserver
|
||||||
|
|
||||||
// VsyncDispatcher is used to dispatch vsync events to the registered observers.
|
// VsyncDispatcher is used to dispatch vsync events to the registered observers.
|
||||||
class VsyncDispatcher
|
class VsyncDispatcher
|
||||||
@@ -44,7 +57,13 @@ class VsyncDispatcher
|
|||||||
public:
|
public:
|
||||||
static VsyncDispatcher* GetInstance();
|
static VsyncDispatcher* GetInstance();
|
||||||
// Called on the vsync thread when a hardware vsync occurs
|
// 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 NotifyVsync(TimeStamp aVsyncTimestamp);
|
||||||
|
void SetVsyncSource(VsyncSource* aVsyncSource);
|
||||||
|
|
||||||
// Compositor vsync observers must be added/removed on the compositor thread
|
// Compositor vsync observers must be added/removed on the compositor thread
|
||||||
void AddCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
|
void AddCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
|
||||||
@@ -61,7 +80,8 @@ private:
|
|||||||
// Can have multiple compositors. On desktop, this is 1 compositor per window
|
// Can have multiple compositors. On desktop, this is 1 compositor per window
|
||||||
Mutex mCompositorObserverLock;
|
Mutex mCompositorObserverLock;
|
||||||
nsTArray<nsRefPtr<VsyncObserver>> mCompositorObservers;
|
nsTArray<nsRefPtr<VsyncObserver>> mCompositorObservers;
|
||||||
};
|
nsRefPtr<VsyncSource> mVsyncSource;
|
||||||
|
}; // VsyncDispatcher
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ private:
|
|||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
};
|
}; // MacWakeLockListener
|
||||||
|
|
||||||
// defined in nsCocoaWindow.mm
|
// defined in nsCocoaWindow.mm
|
||||||
extern int32_t gXULModalLevel;
|
extern int32_t gXULModalLevel;
|
||||||
|
|||||||
Reference in New Issue
Block a user