Line data Source code
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 :
6 : #include "VsyncParent.h"
7 :
8 : #include "BackgroundParent.h"
9 : #include "BackgroundParentImpl.h"
10 : #include "gfxPlatform.h"
11 : #include "mozilla/Unused.h"
12 : #include "nsIThread.h"
13 : #include "nsThreadUtils.h"
14 : #include "VsyncSource.h"
15 :
16 : namespace mozilla {
17 :
18 : using namespace ipc;
19 :
20 : namespace layout {
21 :
22 : /*static*/ already_AddRefed<VsyncParent>
23 1 : VsyncParent::Create()
24 : {
25 1 : AssertIsOnBackgroundThread();
26 2 : RefPtr<gfx::VsyncSource> vsyncSource = gfxPlatform::GetPlatform()->GetHardwareVsync();
27 2 : RefPtr<VsyncParent> vsyncParent = new VsyncParent();
28 1 : vsyncParent->mVsyncDispatcher = vsyncSource->GetRefreshTimerVsyncDispatcher();
29 2 : return vsyncParent.forget();
30 : }
31 :
32 1 : VsyncParent::VsyncParent()
33 : : mObservingVsync(false)
34 : , mDestroyed(false)
35 1 : , mBackgroundThread(NS_GetCurrentThread())
36 : {
37 1 : MOZ_ASSERT(mBackgroundThread);
38 1 : AssertIsOnBackgroundThread();
39 1 : }
40 :
41 0 : VsyncParent::~VsyncParent()
42 : {
43 : // Since we use NS_INLINE_DECL_THREADSAFE_REFCOUNTING, we can't make sure
44 : // VsyncParent is always released on the background thread.
45 0 : }
46 :
47 : bool
48 42 : VsyncParent::NotifyVsync(TimeStamp aTimeStamp)
49 : {
50 : // Called on hardware vsync thread. We should post to current ipc thread.
51 42 : MOZ_ASSERT(!IsOnBackgroundThread());
52 : nsCOMPtr<nsIRunnable> vsyncEvent =
53 84 : NewRunnableMethod<TimeStamp>("layout::VsyncParent::DispatchVsyncEvent",
54 : this,
55 : &VsyncParent::DispatchVsyncEvent,
56 84 : aTimeStamp);
57 42 : MOZ_ALWAYS_SUCCEEDS(mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL));
58 84 : return true;
59 : }
60 :
61 : void
62 42 : VsyncParent::DispatchVsyncEvent(TimeStamp aTimeStamp)
63 : {
64 42 : AssertIsOnBackgroundThread();
65 :
66 : // If we call NotifyVsync() when we handle ActorDestroy() message, we might
67 : // still call DispatchVsyncEvent().
68 : // Similarly, we might also receive RecvUnobserveVsync() when call
69 : // NotifyVsync(). We use mObservingVsync and mDestroyed flags to skip this
70 : // notification.
71 42 : if (mObservingVsync && !mDestroyed) {
72 42 : Unused << SendNotify(aTimeStamp);
73 : }
74 42 : }
75 :
76 : mozilla::ipc::IPCResult
77 1 : VsyncParent::RecvRequestVsyncRate()
78 : {
79 1 : AssertIsOnBackgroundThread();
80 1 : TimeDuration vsyncRate = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay().GetVsyncRate();
81 1 : Unused << SendVsyncRate(vsyncRate.ToMilliseconds());
82 1 : return IPC_OK();
83 : }
84 :
85 : mozilla::ipc::IPCResult
86 2 : VsyncParent::RecvObserve()
87 : {
88 2 : AssertIsOnBackgroundThread();
89 2 : if (!mObservingVsync) {
90 2 : mVsyncDispatcher->AddChildRefreshTimer(this);
91 2 : mObservingVsync = true;
92 2 : return IPC_OK();
93 : }
94 0 : return IPC_FAIL_NO_REASON(this);
95 : }
96 :
97 : mozilla::ipc::IPCResult
98 2 : VsyncParent::RecvUnobserve()
99 : {
100 2 : AssertIsOnBackgroundThread();
101 2 : if (mObservingVsync) {
102 2 : mVsyncDispatcher->RemoveChildRefreshTimer(this);
103 2 : mObservingVsync = false;
104 2 : return IPC_OK();
105 : }
106 0 : return IPC_FAIL_NO_REASON(this);
107 : }
108 :
109 : void
110 0 : VsyncParent::ActorDestroy(ActorDestroyReason aReason)
111 : {
112 0 : MOZ_ASSERT(!mDestroyed);
113 0 : AssertIsOnBackgroundThread();
114 0 : if (mObservingVsync) {
115 0 : mVsyncDispatcher->RemoveChildRefreshTimer(this);
116 : }
117 0 : mVsyncDispatcher = nullptr;
118 0 : mDestroyed = true;
119 0 : }
120 :
121 : } // namespace layout
122 : } // namespace mozilla
|