From 5119b7e4ebf8c6efd3285ff734ebff76d2cf872c Mon Sep 17 00:00:00 2001 From: Mason Chang Date: Thu, 18 Dec 2014 08:30:06 -0800 Subject: [PATCH] Bug 1101974. Part 3 - Create VsyncSource / Display framework. r=kats --- gfx/thebes/VsyncSource.cpp | 66 ++++++++++++++++++++++++++++++++++++++ gfx/thebes/VsyncSource.h | 50 +++++++++++++++++++++++++++++ gfx/thebes/gfxPlatform.cpp | 6 ++-- gfx/thebes/gfxPlatform.h | 20 +++++++++++- gfx/thebes/moz.build | 5 +++ 5 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 gfx/thebes/VsyncSource.cpp create mode 100644 gfx/thebes/VsyncSource.h diff --git a/gfx/thebes/VsyncSource.cpp b/gfx/thebes/VsyncSource.cpp new file mode 100644 index 000000000000..994b933f1706 --- /dev/null +++ b/gfx/thebes/VsyncSource.cpp @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "VsyncSource.h" +#include "gfxPlatform.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/VsyncDispatcher.h" + +using namespace mozilla; +using namespace mozilla::gfx; + +void +VsyncSource::AddVsyncDispatcher(VsyncDispatcher* aVsyncDispatcher) +{ + MOZ_ASSERT(NS_IsMainThread()); + GetGlobalDisplay().AddVsyncDispatcher(aVsyncDispatcher); +} + +void +VsyncSource::RemoveVsyncDispatcher(VsyncDispatcher* aVsyncDispatcher) +{ + MOZ_ASSERT(NS_IsMainThread()); + GetGlobalDisplay().RemoveVsyncDispatcher(aVsyncDispatcher); +} + +VsyncSource::Display& +VsyncSource::FindDisplay(VsyncDispatcher* aVsyncDispatcher) +{ + return GetGlobalDisplay(); +} + +void +VsyncSource::Display::NotifyVsync(TimeStamp aVsyncTimestamp) +{ + // Called on the hardware vsync thread + for (size_t i = 0; i < mVsyncDispatchers.Length(); i++) { + mVsyncDispatchers[i]->NotifyVsync(aVsyncTimestamp); + } +} + +VsyncSource::Display::Display() +{ + MOZ_ASSERT(NS_IsMainThread()); +} + +VsyncSource::Display::~Display() +{ + MOZ_ASSERT(NS_IsMainThread()); + mVsyncDispatchers.Clear(); +} + +void +VsyncSource::Display::AddVsyncDispatcher(VsyncDispatcher* aVsyncDispatcher) +{ + MOZ_ASSERT(NS_IsMainThread()); + mVsyncDispatchers.AppendElement(aVsyncDispatcher); +} + +void +VsyncSource::Display::RemoveVsyncDispatcher(VsyncDispatcher* aVsyncDispatcher) +{ + MOZ_ASSERT(NS_IsMainThread()); + mVsyncDispatchers.RemoveElement(aVsyncDispatcher); +} diff --git a/gfx/thebes/VsyncSource.h b/gfx/thebes/VsyncSource.h new file mode 100644 index 000000000000..343753f7652a --- /dev/null +++ b/gfx/thebes/VsyncSource.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/RefPtr.h" +#include "mozilla/TimeStamp.h" +#include "nsISupportsImpl.h" +#include "nsTArray.h" + +namespace mozilla { +class VsyncDispatcher; + +namespace gfx { + +// Controls how and when to enable/disable vsync. Lives as long as the +// gfxPlatform does on the parent process +class VsyncSource +{ + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncSource) +public: + // Controls vsync unique to each display and unique on each platform + class Display { + public: + Display(); + virtual ~Display(); + void AddVsyncDispatcher(mozilla::VsyncDispatcher* aVsyncDispatcher); + void RemoveVsyncDispatcher(mozilla::VsyncDispatcher* aVsyncDispatcher); + // Notified when this display's vsync occurs, on the hardware vsync thread + void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp); + + // These should all only be called on the main thread + virtual void EnableVsync() = 0; + virtual void DisableVsync() = 0; + virtual bool IsVsyncEnabled() = 0; + + private: + nsTArray> mVsyncDispatchers; + }; // end Display + + void AddVsyncDispatcher(mozilla::VsyncDispatcher* aVsyncDispatcher); + void RemoveVsyncDispatcher(mozilla::VsyncDispatcher* aVsyncDispatcher); + +protected: + virtual Display& GetGlobalDisplay() = 0; // Works across all displays + virtual Display& FindDisplay(mozilla::VsyncDispatcher* aVsyncDispatcher); + virtual ~VsyncSource() {} +}; // VsyncSource +} // gfx +} // mozilla diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 8faba21fba04..5de9c530b2fe 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -104,6 +104,7 @@ class mozilla::gl::SkiaGLGlue : public GenericAtomicRefCounted { #include "nsIGfxInfo.h" #include "nsIXULRuntime.h" +#include "VsyncSource.h" namespace mozilla { namespace layers { @@ -548,8 +549,8 @@ gfxPlatform::Init() RegisterStrongMemoryReporter(new GfxMemoryImageReporter()); - if (gfxPrefs::HardwareVsyncEnabled() && gfxPrefs::VsyncAlignedCompositor()) { - gPlatform->InitHardwareVsync(); + if (XRE_IsParentProcess() && gfxPrefs::HardwareVsyncEnabled()) { + gPlatform->mVsyncSource = gPlatform->CreateHardwareVsyncSource(); } } @@ -597,6 +598,7 @@ gfxPlatform::Shutdown() gPlatform->mMemoryPressureObserver = nullptr; gPlatform->mSkiaGlue = nullptr; + gPlatform->mVsyncSource = nullptr; } #ifdef MOZ_WIDGET_ANDROID diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 30529b37d5d6..3320642a8941 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -50,6 +50,7 @@ class SourceSurface; class DataSourceSurface; class ScaledFont; class DrawEventRecorder; +class VsyncSource; inline uint32_t BackendTypeBit(BackendType b) @@ -583,6 +584,17 @@ public: static bool UsesOffMainThreadCompositing(); bool HasEnoughTotalSystemMemoryForSkiaGL(); + + /** + * Get the hardware vsync source for each platform. + * Should only exist and be valid on the parent process + */ + virtual mozilla::gfx::VsyncSource* GetHardwareVsync() { + MOZ_ASSERT(mVsyncSource != nullptr); + MOZ_ASSERT(XRE_IsParentProcess()); + return mVsyncSource; + } + protected: gfxPlatform(); virtual ~gfxPlatform(); @@ -593,7 +605,10 @@ protected: /** * Initialized hardware vsync based on each platform. */ - virtual void InitHardwareVsync() {} + virtual already_AddRefed CreateHardwareVsyncSource() { + NS_WARNING("Hardware vsync not supported on platform yet"); + return nullptr; + } /** * Helper method, creates a draw target for a specific Azure backend. @@ -659,6 +674,9 @@ protected: uint32_t mTotalSystemMemory; + // Hardware vsync source. Only valid on parent process + nsRefPtr mVsyncSource; + private: /** * Start up Thebes. diff --git a/gfx/thebes/moz.build b/gfx/thebes/moz.build index f0b8d284d5b3..5764eee2e20e 100644 --- a/gfx/thebes/moz.build +++ b/gfx/thebes/moz.build @@ -52,6 +52,7 @@ EXPORTS += [ 'gfxVR.h', 'GraphicsFilter.h', 'RoundedRect.h', + 'VsyncSource.h', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': @@ -246,6 +247,7 @@ UNIFIED_SOURCES += [ 'gfxUtils.cpp', 'gfxVR.cpp', 'nsUnicodeRange.cpp', + 'VsyncSource.cpp', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': @@ -269,6 +271,9 @@ LOCAL_INCLUDES += [ '/dom/xml', ] +if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': + LOCAL_INCLUDES += ['/widget/gonk'] + if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'qt'): DEFINES['MOZ_ENABLE_FREETYPE'] = True