Bug 1118841 - Implement the RefreshTimerVsyncDispatcher. r=kats
--- a/gfx/thebes/VsyncSource.cpp
+++ b/gfx/thebes/VsyncSource.cpp
@@ -2,16 +2,17 @@
* 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"
+#include "MainThreadUtils.h"
using namespace mozilla;
using namespace mozilla::gfx;
void
VsyncSource::AddCompositorVsyncDispatcher(CompositorVsyncDispatcher* aCompositorVsyncDispatcher)
{
MOZ_ASSERT(NS_IsMainThread());
--- a/widget/VsyncDispatcher.cpp
+++ b/widget/VsyncDispatcher.cpp
@@ -1,73 +1,121 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "MainThreadUtils.h"
#include "VsyncDispatcher.h"
-#include "mozilla/ClearOnShutdown.h"
+#include "VsyncSource.h"
+#include "gfxPlatform.h"
#include "mozilla/layers/CompositorParent.h"
-#include "gfxPrefs.h"
-#include "gfxPlatform.h"
-#include "VsyncSource.h"
#ifdef MOZ_ENABLE_PROFILER_SPS
#include "GeckoProfiler.h"
#include "ProfilerMarkers.h"
#endif
-#ifdef MOZ_WIDGET_GONK
-#include "GeckoTouchDispatcher.h"
-#endif
-
-using namespace mozilla::layers;
-
namespace mozilla {
CompositorVsyncDispatcher::CompositorVsyncDispatcher()
: mCompositorObserverLock("CompositorObserverLock")
{
MOZ_ASSERT(XRE_IsParentProcess());
+ MOZ_ASSERT(NS_IsMainThread());
gfxPlatform::GetPlatform()->GetHardwareVsync()->AddCompositorVsyncDispatcher(this);
}
CompositorVsyncDispatcher::~CompositorVsyncDispatcher()
{
+ MOZ_ASSERT(XRE_IsParentProcess());
// We auto remove this vsync dispatcher from the vsync source in the nsBaseWidget
MOZ_ASSERT(NS_IsMainThread());
}
void
CompositorVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
{
// In hardware vsync thread
#ifdef MOZ_ENABLE_PROFILER_SPS
if (profiler_is_active()) {
- CompositorParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
+ layers::CompositorParent::PostInsertVsyncProfilerMarker(aVsyncTimestamp);
}
#endif
MutexAutoLock lock(mCompositorObserverLock);
- if (gfxPrefs::VsyncAlignedCompositor() && mCompositorVsyncObserver) {
+ if (mCompositorVsyncObserver) {
mCompositorVsyncObserver->NotifyVsync(aVsyncTimestamp);
}
}
void
CompositorVsyncDispatcher::SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver)
{
- MOZ_ASSERT(CompositorParent::IsInCompositorThread());
+ MOZ_ASSERT(layers::CompositorParent::IsInCompositorThread());
MutexAutoLock lock(mCompositorObserverLock);
mCompositorVsyncObserver = aVsyncObserver;
}
void
CompositorVsyncDispatcher::Shutdown()
{
// Need to explicitly remove CompositorVsyncDispatcher when the nsBaseWidget shuts down.
// Otherwise, we would get dead vsync notifications between when the nsBaseWidget
// shuts down and the CompositorParent shuts down.
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
gfxPlatform::GetPlatform()->GetHardwareVsync()->RemoveCompositorVsyncDispatcher(this);
}
+
+RefreshTimerVsyncDispatcher::RefreshTimerVsyncDispatcher()
+ : mRefreshTimersLock("RefreshTimers lock")
+{
+ MOZ_ASSERT(XRE_IsParentProcess());
+ MOZ_ASSERT(NS_IsMainThread());
+}
+
+RefreshTimerVsyncDispatcher::~RefreshTimerVsyncDispatcher()
+{
+ MOZ_ASSERT(XRE_IsParentProcess());
+ MOZ_ASSERT(NS_IsMainThread());
+}
+
+void
+RefreshTimerVsyncDispatcher::NotifyVsync(TimeStamp aVsyncTimestamp)
+{
+ MutexAutoLock lock(mRefreshTimersLock);
+
+ for (size_t i = 0; i < mChildRefreshTimers.Length(); i++) {
+ mChildRefreshTimers[i]->NotifyVsync(aVsyncTimestamp);
+ }
+
+ if (mParentRefreshTimer) {
+ mParentRefreshTimer->NotifyVsync(aVsyncTimestamp);
+ }
+}
+
+void
+RefreshTimerVsyncDispatcher::SetParentRefreshTimer(VsyncObserver* aVsyncObserver)
+{
+ MutexAutoLock lock(mRefreshTimersLock);
+ mParentRefreshTimer = aVsyncObserver;
+}
+
+void
+RefreshTimerVsyncDispatcher::AddChildRefreshTimer(VsyncObserver* aVsyncObserver)
+{
+ MutexAutoLock lock(mRefreshTimersLock);
+ MOZ_ASSERT(aVsyncObserver);
+ if (!mChildRefreshTimers.Contains(aVsyncObserver)) {
+ mChildRefreshTimers.AppendElement(aVsyncObserver);
+ }
+}
+
+void
+RefreshTimerVsyncDispatcher::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver)
+{
+ MutexAutoLock lock(mRefreshTimersLock);
+ MOZ_ASSERT(aVsyncObserver);
+ mChildRefreshTimers.RemoveElement(aVsyncObserver);
+}
+
} // namespace mozilla
--- a/widget/VsyncDispatcher.h
+++ b/widget/VsyncDispatcher.h
@@ -1,46 +1,46 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef mozilla_widget_VsyncDispatcher_h
#define mozilla_widget_VsyncDispatcher_h
-#include "base/message_loop.h"
#include "mozilla/Mutex.h"
+#include "mozilla/TimeStamp.h"
#include "nsISupportsImpl.h"
#include "nsTArray.h"
-#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
+#include "nsRefPtr.h"
namespace mozilla {
-class TimeStamp;
-
-namespace layers {
-class CompositorVsyncObserver;
-}
class VsyncObserver
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VsyncObserver)
public:
// The method called when a vsync occurs. Return true if some work was done.
- // Vsync notifications will occur on the hardware vsync thread
+ // In general, this vsync notification will occur on the hardware vsync
+ // thread from VsyncSource. But it might also be called on PVsync ipc thread
+ // if this notification is cross process. Thus all observer should check the
+ // thread model before handling the real task.
virtual bool NotifyVsync(TimeStamp aVsyncTimestamp) = 0;
protected:
VsyncObserver() {}
virtual ~VsyncObserver() {}
}; // VsyncObserver
+// Used to dispatch vsync events in the parent process to compositors
class CompositorVsyncDispatcher MOZ_FINAL
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorVsyncDispatcher)
+
public:
CompositorVsyncDispatcher();
// 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
@@ -48,15 +48,46 @@ public:
void NotifyVsync(TimeStamp aVsyncTimestamp);
// Compositor vsync observers must be added/removed on the compositor thread
void SetCompositorVsyncObserver(VsyncObserver* aVsyncObserver);
void Shutdown();
private:
virtual ~CompositorVsyncDispatcher();
+
Mutex mCompositorObserverLock;
nsRefPtr<VsyncObserver> mCompositorVsyncObserver;
};
+// Dispatch vsync event to ipc actor parent and chrome RefreshTimer.
+class RefreshTimerVsyncDispatcher MOZ_FINAL
+{
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefreshTimerVsyncDispatcher)
+
+public:
+ RefreshTimerVsyncDispatcher();
+
+ // Please check CompositorVsyncDispatcher::NotifyVsync().
+ void NotifyVsync(TimeStamp aVsyncTimestamp);
+
+ // Set chrome process's RefreshTimer to this dispatcher.
+ // This function can be called from any thread.
+ void SetParentRefreshTimer(VsyncObserver* aVsyncObserver);
+
+ // Add or remove the content process' RefreshTimer to this dispatcher. This
+ // will be a no-op for AddChildRefreshTimer() if the observer is already
+ // registered.
+ // These functions can be called from any thread.
+ void AddChildRefreshTimer(VsyncObserver* aVsyncObserver);
+ void RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver);
+
+private:
+ virtual ~RefreshTimerVsyncDispatcher();
+
+ Mutex mRefreshTimersLock;
+ nsRefPtr<VsyncObserver> mParentRefreshTimer;
+ nsTArray<nsRefPtr<VsyncObserver>> mChildRefreshTimers;
+};
+
} // namespace mozilla
-#endif // __mozilla_widget_VsyncDispatcher_h
+#endif // mozilla_widget_VsyncDispatcher_h