VsyncDispatcher.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "MainThreadUtils.h"
  6. #include "VsyncDispatcher.h"
  7. #include "VsyncSource.h"
  8. #include "gfxPlatform.h"
  9. #include "mozilla/layers/Compositor.h"
  10. #include "mozilla/layers/CompositorBridgeParent.h"
  11. #include "mozilla/layers/CompositorThread.h"
  12. namespace mozilla {
  13. CompositorVsyncDispatcher::CompositorVsyncDispatcher()
  14. : mCompositorObserverLock("CompositorObserverLock")
  15. , mDidShutdown(false)
  16. {
  17. MOZ_ASSERT(XRE_IsParentProcess());
  18. MOZ_ASSERT(NS_IsMainThread());
  19. }
  20. CompositorVsyncDispatcher::~CompositorVsyncDispatcher()
  21. {
  22. MOZ_ASSERT(XRE_IsParentProcess());
  23. // We auto remove this vsync dispatcher from the vsync source in the nsBaseWidget
  24. }
  25. void
  26. CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
  27. {
  28. MutexAutoLock lock(mCompositorObserverLock);
  29. if (mCompositorVsyncObserver) {
  30. mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
  31. }
  32. }
  33. void
  34. CompositorVsyncDispatcher::ObserveVsync(bool aEnable)
  35. {
  36. MOZ_ASSERT(NS_IsMainThread());
  37. MOZ_ASSERT(XRE_IsParentProcess());
  38. if (mDidShutdown) {
  39. return;
  40. }
  41. if (aEnable) {
  42. gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
  43. } else {
  44. gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveCompositorVsyncDispatcher(this);
  45. }
  46. }
  47. void
  48. CompositorVsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
  49. {
  50. // When remote compositing or running gtests, vsync observation is
  51. // initiated on the main thread. Otherwise, it is initiated from the compositor
  52. // thread.
  53. MOZ_ASSERT(NS_IsMainThread() || CompositorThreadHolder::IsInCompositorThread());
  54. { // scope lock
  55. MutexAutoLock lock(mCompositorObserverLock);
  56. mCompositorVsyncObserver = aVsyncObserver;
  57. }
  58. bool observeVsync = aVsyncObserver != nullptr;
  59. nsCOMPtr<nsIRunnable> vsyncControl = NewRunnableMethod<bool>(this,
  60. &CompositorVsyncDispatcher::ObserveVsync,
  61. observeVsync);
  62. NS_DispatchToMainThread(vsyncControl);
  63. }
  64. void
  65. CompositorVsyncDispatcher::Shutdown()
  66. {
  67. // Need to explicitly remove CompositorVsyncDispatcher when the nsBaseWidget shuts down.
  68. // Otherwise, we would get dead vsync notifications between when the nsBaseWidget
  69. // shuts down and the CompositorBridgeParent shuts down.
  70. MOZ_ASSERT(XRE_IsParentProcess());
  71. MOZ_ASSERT(NS_IsMainThread());
  72. ObserveVsync(false);
  73. mDidShutdown = true;
  74. { // scope lock
  75. MutexAutoLock lock(mCompositorObserverLock);
  76. mCompositorVsyncObserver = nullptr;
  77. }
  78. }
  79. RefreshTimerVsyncDispatcher::RefreshTimerVsyncDispatcher()
  80. : mRefreshTimersLock("RefreshTimers lock")
  81. {
  82. MOZ_ASSERT(XRE_IsParentProcess());
  83. MOZ_ASSERT(NS_IsMainThread());
  84. }
  85. RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher()
  86. {
  87. MOZ_ASSERT(XRE_IsParentProcess());
  88. MOZ_ASSERT(NS_IsMainThread());
  89. }
  90. void
  91. RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
  92. {
  93. MutexAutoLock lock(mRefreshTimersLock);
  94. for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
  95. mChildRefreshTimers[i]->NotifyVsync(aVsyncTimestamp);
  96. }
  97. if (mParentRefreshTimer) {
  98. mParentRefreshTimer->NotifyVsync(aVsyncTimestamp);
  99. }
  100. }
  101. void
  102. RefreshTimerVsyncDispatcher::SetParentRefreshTimer(VsyncObserver* aVsyncObserver)
  103. {
  104. MOZ_ASSERT(NS_IsMainThread());
  105. { // lock scope because UpdateVsyncStatus runs on main thread and will deadlock
  106. MutexAutoLock lock(mRefreshTimersLock);
  107. mParentRefreshTimer = aVsyncObserver;
  108. }
  109. UpdateVsyncStatus();
  110. }
  111. void
  112. RefreshTimerVsyncDispatcher::AddChildRefreshTimer(VsyncObserver* aVsyncObserver)
  113. {
  114. { // scope lock - called on pbackground thread
  115. MutexAutoLock lock(mRefreshTimersLock);
  116. MOZ_ASSERT(aVsyncObserver);
  117. if (!mChildRefreshTimers.Contains(aVsyncObserver)) {
  118. mChildRefreshTimers.AppendElement(aVsyncObserver);
  119. }
  120. }
  121. UpdateVsyncStatus();
  122. }
  123. void
  124. RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver)
  125. {
  126. { // scope lock - called on pbackground thread
  127. MutexAutoLock lock(mRefreshTimersLock);
  128. MOZ_ASSERT(aVsyncObserver);
  129. mChildRefreshTimers.RemoveElement(aVsyncObserver);
  130. }
  131. UpdateVsyncStatus();
  132. }
  133. void
  134. RefreshTimerVsyncDispatcher::UpdateVsyncStatus()
  135. {
  136. if (!NS_IsMainThread()) {
  137. NS_DispatchToMainThread(NewRunnableMethod(this,
  138. &RefreshTimerVsyncDispatcher::UpdateVsyncStatus));
  139. return;
  140. }
  141. gfx::VsyncSource::Display& display = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
  142. display.NotifyRefreshTimerVsyncStatus(NeedsVsync());
  143. }
  144. bool
  145. RefreshTimerVsyncDispatcher::NeedsVsync()
  146. {
  147. MOZ_ASSERT(NS_IsMainThread());
  148. MutexAutoLock lock(mRefreshTimersLock);
  149. return (mParentRefreshTimer != nullptr) || !mChildRefreshTimers.IsEmpty();
  150. }
  151. } // namespace mozilla