From 528489e5206af3030c74b0678477e8ae4f93dfee Mon Sep 17 00:00:00 2001 From: Mason Chang Date: Thu, 18 Dec 2014 08:30:06 -0800 Subject: [PATCH] Bug 1101974. Part 4 - Refactor VsyncSource on OS X. r=mstange --- gfx/thebes/gfxPlatformMac.cpp | 123 ++++++++++++++++++++-------------- gfx/thebes/gfxPlatformMac.h | 9 ++- 2 files changed, 78 insertions(+), 54 deletions(-) diff --git a/gfx/thebes/gfxPlatformMac.cpp b/gfx/thebes/gfxPlatformMac.cpp index 3d3bad6dffc..6b4bfc070a8 100644 --- a/gfx/thebes/gfxPlatformMac.cpp +++ b/gfx/thebes/gfxPlatformMac.cpp @@ -26,6 +26,8 @@ #include #include "nsCocoaFeatures.h" +#include "mozilla/layers/CompositorParent.h" +#include "VsyncSource.h" using namespace mozilla; using namespace mozilla::gfx; @@ -38,7 +40,7 @@ typedef uint32_t AutoActivationSetting; // bug 567552 - disable auto-activation of fonts -static void +static void DisableFontActivation() { // get the main bundle identifier @@ -429,81 +431,98 @@ static CVReturn VsyncCallback(CVDisplayLinkRef aDisplayLink, 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; - } + VsyncSource::Display* display = (VsyncSource::Display*) aDisplayLinkContext; + int64_t timestamp = aOutputTime->hostTime; + mozilla::TimeStamp vsyncTime = mozilla::TimeStamp::FromSystemTime(timestamp); + display->NotifyVsync(vsyncTime); + return kCVReturnSuccess; } -class OSXVsyncSource MOZ_FINAL : public mozilla::VsyncSource +class OSXVsyncSource MOZ_FINAL : public VsyncSource { public: OSXVsyncSource() { - EnableVsync(); } - virtual void EnableVsync() MOZ_OVERRIDE + virtual Display& GetGlobalDisplay() 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; - } + return mGlobalDisplay; } - virtual void DisableVsync() MOZ_OVERRIDE +protected: + class OSXDisplay MOZ_FINAL : public VsyncSource::Display { - // Release the display link - if (mDisplayLink) { - CVDisplayLinkRelease(mDisplayLink); - mDisplayLink = nullptr; + public: + OSXDisplay() + { + EnableVsync(); } - } - virtual bool IsVsyncEnabled() MOZ_OVERRIDE - { - return mDisplayLink != nullptr; - } + ~OSXDisplay() + { + DisableVsync(); + } + + virtual void EnableVsync() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + // 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; + } + + if (CVDisplayLinkSetOutputCallback(mDisplayLink, &VsyncCallback, this) != kCVReturnSuccess) { + NS_WARNING("Could not set displaylink output callback"); + return; + } + + if (CVDisplayLinkStart(mDisplayLink) != kCVReturnSuccess) { + NS_WARNING("Could not activate the display link"); + mDisplayLink = nullptr; + } + } + + virtual void DisableVsync() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + // Release the display link + if (mDisplayLink) { + CVDisplayLinkRelease(mDisplayLink); + mDisplayLink = nullptr; + } + } + + virtual bool IsVsyncEnabled() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + return mDisplayLink != nullptr; + } + + private: + // Manages the display link render thread + CVDisplayLinkRef mDisplayLink; + }; // OSXDisplay private: virtual ~OSXVsyncSource() { - DisableVsync(); } - // Manages the display link render thread - CVDisplayLinkRef mDisplayLink; + OSXDisplay mGlobalDisplay; }; // OSXVsyncSource -void -gfxPlatformMac::InitHardwareVsync() +already_AddRefed +gfxPlatformMac::CreateHardwareVsyncSource() { nsRefPtr osxVsyncSource = new OSXVsyncSource(); - mozilla::VsyncDispatcher::GetInstance()->SetVsyncSource(osxVsyncSource); + return osxVsyncSource.forget(); } void diff --git a/gfx/thebes/gfxPlatformMac.h b/gfx/thebes/gfxPlatformMac.h index bf06fb446a2..1ba32db2abb 100644 --- a/gfx/thebes/gfxPlatformMac.h +++ b/gfx/thebes/gfxPlatformMac.h @@ -9,7 +9,12 @@ #include "nsTArrayForwardDeclare.h" #include "gfxPlatform.h" -namespace mozilla { namespace gfx { class DrawTarget; }} +namespace mozilla { +namespace gfx { +class DrawTarget; +class VsyncSource; +} // gfx +} // mozilla class gfxPlatformMac : public gfxPlatform { public: @@ -67,7 +72,7 @@ public: virtual bool UseTiling() MOZ_OVERRIDE; virtual bool UseProgressivePaint() MOZ_OVERRIDE; - virtual void InitHardwareVsync() MOZ_OVERRIDE; + virtual already_AddRefed CreateHardwareVsyncSource() MOZ_OVERRIDE; // lower threshold on font anti-aliasing uint32_t GetAntiAliasingThreshold() { return mFontAntiAliasingThreshold; }