From 81083d3e3b6046146b576e9e3244abe001aa0323 Mon Sep 17 00:00:00 2001 From: JerryShih Date: Tue, 13 Jan 2015 08:04:00 -0500 Subject: [PATCH] Bug 1119742 - Add RefreshTimerDispatcher into VsyncSource::Display. r=kats 1) Create RefreshTimerDispatcher in VsyncSource::Display. 2) Use mutex for all VsyncSource::Display's member access. --- gfx/thebes/VsyncSource.cpp | 66 +++++++++++++++++++++++++++----------- gfx/thebes/VsyncSource.h | 41 +++++++++++++++-------- 2 files changed, 76 insertions(+), 31 deletions(-) diff --git a/gfx/thebes/VsyncSource.cpp b/gfx/thebes/VsyncSource.cpp index 091134565671..71edf9b93359 100644 --- a/gfx/thebes/VsyncSource.cpp +++ b/gfx/thebes/VsyncSource.cpp @@ -4,64 +4,94 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "VsyncSource.h" -#include "gfxPlatform.h" -#include "mozilla/TimeStamp.h" +#include "nsThreadUtils.h" +#include "nsXULAppAPI.h" #include "mozilla/VsyncDispatcher.h" #include "MainThreadUtils.h" -using namespace mozilla; -using namespace mozilla::gfx; +namespace mozilla { +namespace gfx { void VsyncSource::AddCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher) { + MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(NS_IsMainThread()); + // Just use the global display until we have enough information to get the + // corresponding display for compositor. GetGlobalDisplay().AddCompositorVsyncDispatcher(aCompositorVsyncDispatcher); } void VsyncSource::RemoveCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher) { + MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(NS_IsMainThread()); + // See also AddCompositorVsyncDispatcher(). GetGlobalDisplay().RemoveCompositorVsyncDispatcher(aCompositorVsyncDispatcher); } -VsyncSource::Display& -VsyncSource::FindDisplay(CompositorVsyncDispatcher* aCompositorVsyncDispatcher) +nsRefPtr +VsyncSource::GetRefreshTimerVsyncDispatcher() { - return GetGlobalDisplay(); + MOZ_ASSERT(XRE_IsParentProcess()); + // See also AddCompositorVsyncDispatcher(). + return GetGlobalDisplay().GetRefreshTimerVsyncDispatcher(); +} + +VsyncSource::Display::Display() + : mDispatcherLock("display dispatcher lock") +{ + MOZ_ASSERT(NS_IsMainThread()); + mRefreshTimerVsyncDispatcher = new RefreshTimerVsyncDispatcher(); +} + +VsyncSource::Display::~Display() +{ + MOZ_ASSERT(NS_IsMainThread()); + MutexAutoLock lock(mDispatcherLock); + mRefreshTimerVsyncDispatcher = nullptr; + mCompositorVsyncDispatchers.Clear(); } void VsyncSource::Display::NotifyVsync(TimeStamp aVsyncTimestamp) { // Called on the vsync thread + MutexAutoLock lock(mDispatcherLock); + for (size_t i = 0; i < mCompositorVsyncDispatchers.Length(); i++) { mCompositorVsyncDispatchers[i]->NotifyVsync(aVsyncTimestamp); } -} -VsyncSource::Display::Display() -{ - MOZ_ASSERT(NS_IsMainThread()); -} - -VsyncSource::Display::~Display() -{ - MOZ_ASSERT(NS_IsMainThread()); - mCompositorVsyncDispatchers.Clear(); + mRefreshTimerVsyncDispatcher->NotifyVsync(aVsyncTimestamp); } void VsyncSource::Display::AddCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher) { MOZ_ASSERT(NS_IsMainThread()); - mCompositorVsyncDispatchers.AppendElement(aCompositorVsyncDispatcher); + MOZ_ASSERT(aCompositorVsyncDispatcher); + MutexAutoLock lock(mDispatcherLock); + if (!mCompositorVsyncDispatchers.Contains(aCompositorVsyncDispatcher)) { + mCompositorVsyncDispatchers.AppendElement(aCompositorVsyncDispatcher); + } } void VsyncSource::Display::RemoveCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher) { MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aCompositorVsyncDispatcher); + MutexAutoLock lock(mDispatcherLock); mCompositorVsyncDispatchers.RemoveElement(aCompositorVsyncDispatcher); } + +nsRefPtr +VsyncSource::Display::GetRefreshTimerVsyncDispatcher() +{ + return mRefreshTimerVsyncDispatcher; +} + +} //namespace gfx +} //namespace mozilla diff --git a/gfx/thebes/VsyncSource.h b/gfx/thebes/VsyncSource.h index 240b95e8f798..4ca844b2841c 100644 --- a/gfx/thebes/VsyncSource.h +++ b/gfx/thebes/VsyncSource.h @@ -6,12 +6,14 @@ #ifndef GFX_VSYNCSOURCE_H #define GFX_VSYNCSOURCE_H -#include "mozilla/RefPtr.h" +#include "nsTArray.h" +#include "nsRefPtr.h" +#include "mozilla/Mutex.h" #include "mozilla/TimeStamp.h" #include "nsISupportsImpl.h" -#include "nsTArray.h" namespace mozilla { +class RefreshTimerVsyncDispatcher; class CompositorVsyncDispatcher; namespace gfx { @@ -21,14 +23,17 @@ namespace gfx { class VsyncSource { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncSource) + + typedef mozilla::RefreshTimerVsyncDispatcher RefreshTimerVsyncDispatcher; + typedef mozilla::CompositorVsyncDispatcher CompositorVsyncDispatcher; + public: // Controls vsync unique to each display and unique on each platform class Display { public: Display(); virtual ~Display(); - void AddCompositorVsyncDispatcher(mozilla::CompositorVsyncDispatcher* aCompositorVsyncDispatcher); - void RemoveCompositorVsyncDispatcher(mozilla::CompositorVsyncDispatcher* aCompositorVsyncDispatcher); + // Notified when this display's vsync occurs, on the vsync thread // The aVsyncTimestamp should normalize to the Vsync time that just occured // However, different platforms give different vsync notification times. @@ -38,7 +43,12 @@ public: // Android: TODO // All platforms should normalize to the vsync that just occured. // Large parts of Gecko assume TimeStamps should not be in the future such as animations - virtual void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp); + virtual void NotifyVsync(TimeStamp aVsyncTimestamp); + + nsRefPtr GetRefreshTimerVsyncDispatcher(); + + void AddCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher); + void RemoveCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher); // These should all only be called on the main thread virtual void EnableVsync() = 0; @@ -46,18 +56,23 @@ public: virtual bool IsVsyncEnabled() = 0; private: - nsTArray> mCompositorVsyncDispatchers; - }; // end Display + Mutex mDispatcherLock; + nsTArray> mCompositorVsyncDispatchers; + nsRefPtr mRefreshTimerVsyncDispatcher; + }; - void AddCompositorVsyncDispatcher(mozilla::CompositorVsyncDispatcher* aCompositorVsyncDispatcher); - void RemoveCompositorVsyncDispatcher(mozilla::CompositorVsyncDispatcher* aCompositorVsyncDispatcher); + void AddCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher); + void RemoveCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher); + + nsRefPtr GetRefreshTimerVsyncDispatcher(); protected: virtual Display& GetGlobalDisplay() = 0; // Works across all displays - virtual Display& FindDisplay(mozilla::CompositorVsyncDispatcher* aCompositorVsyncDispatcher); + virtual ~VsyncSource() {} -}; // VsyncSource -} // gfx -} // mozilla +}; + +} // namespace gfx +} // namespace mozilla #endif /* GFX_VSYNCSOURCE_H */