summaryrefslogtreecommitdiff
path: root/layout/ipc/VsyncParent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/ipc/VsyncParent.cpp')
-rw-r--r--layout/ipc/VsyncParent.cpp121
1 files changed, 121 insertions, 0 deletions
diff --git a/layout/ipc/VsyncParent.cpp b/layout/ipc/VsyncParent.cpp
new file mode 100644
index 0000000000..8ffe8abc4c
--- /dev/null
+++ b/layout/ipc/VsyncParent.cpp
@@ -0,0 +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 "VsyncParent.h"
+
+#include "BackgroundParent.h"
+#include "BackgroundParentImpl.h"
+#include "gfxPlatform.h"
+#include "mozilla/Unused.h"
+#include "nsIThread.h"
+#include "nsThreadUtils.h"
+#include "VsyncSource.h"
+
+namespace mozilla {
+
+using namespace ipc;
+
+namespace layout {
+
+/*static*/ already_AddRefed<VsyncParent>
+VsyncParent::Create()
+{
+ AssertIsOnBackgroundThread();
+ RefPtr<gfx::VsyncSource> vsyncSource = gfxPlatform::GetPlatform()->GetHardwareVsync();
+ RefPtr<VsyncParent> vsyncParent = new VsyncParent();
+ vsyncParent->mVsyncDispatcher = vsyncSource->GetRefreshTimerVsyncDispatcher();
+ return vsyncParent.forget();
+}
+
+VsyncParent::VsyncParent()
+ : mObservingVsync(false)
+ , mDestroyed(false)
+ , mBackgroundThread(NS_GetCurrentThread())
+{
+ MOZ_ASSERT(mBackgroundThread);
+ AssertIsOnBackgroundThread();
+}
+
+VsyncParent::~VsyncParent()
+{
+ // Since we use NS_INLINE_DECL_THREADSAFE_REFCOUNTING, we can't make sure
+ // VsyncParent is always released on the background thread.
+}
+
+bool
+VsyncParent::NotifyVsync(TimeStamp aTimeStamp)
+{
+ // Called on hardware vsync thread. We should post to current ipc thread.
+ MOZ_ASSERT(!IsOnBackgroundThread());
+ nsCOMPtr<nsIRunnable> vsyncEvent =
+ NewRunnableMethod<TimeStamp>(this,
+ &VsyncParent::DispatchVsyncEvent,
+ aTimeStamp);
+ MOZ_ALWAYS_SUCCEEDS(mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL));
+ return true;
+}
+
+void
+VsyncParent::DispatchVsyncEvent(TimeStamp aTimeStamp)
+{
+ AssertIsOnBackgroundThread();
+
+ // If we call NotifyVsync() when we handle ActorDestroy() message, we might
+ // still call DispatchVsyncEvent().
+ // Similarly, we might also receive RecvUnobserveVsync() when call
+ // NotifyVsync(). We use mObservingVsync and mDestroyed flags to skip this
+ // notification.
+ if (mObservingVsync && !mDestroyed) {
+ Unused << SendNotify(aTimeStamp);
+ }
+}
+
+bool
+VsyncParent::RecvRequestVsyncRate()
+{
+ AssertIsOnBackgroundThread();
+ TimeDuration vsyncRate = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay().GetVsyncRate();
+ Unused << SendVsyncRate(vsyncRate.ToMilliseconds());
+ return true;
+}
+
+bool
+VsyncParent::RecvObserve()
+{
+ AssertIsOnBackgroundThread();
+ if (!mObservingVsync) {
+ mVsyncDispatcher->AddChildRefreshTimer(this);
+ mObservingVsync = true;
+ return true;
+ }
+ return false;
+}
+
+bool
+VsyncParent::RecvUnobserve()
+{
+ AssertIsOnBackgroundThread();
+ if (mObservingVsync) {
+ mVsyncDispatcher->RemoveChildRefreshTimer(this);
+ mObservingVsync = false;
+ return true;
+ }
+ return false;
+}
+
+void
+VsyncParent::ActorDestroy(ActorDestroyReason aReason)
+{
+ MOZ_ASSERT(!mDestroyed);
+ AssertIsOnBackgroundThread();
+ if (mObservingVsync) {
+ mVsyncDispatcher->RemoveChildRefreshTimer(this);
+ }
+ mVsyncDispatcher = nullptr;
+ mDestroyed = true;
+}
+
+} // namespace layout
+} // namespace mozilla