VsyncParent.cpp (3034B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "VsyncParent.h" 8 9 #include "nsIThread.h" 10 #include "nsThreadUtils.h" 11 12 namespace mozilla::dom { 13 14 VsyncParent::VsyncParent() 15 : mObservingVsync(false), 16 mDestroyed(false), 17 mInitialThread(NS_GetCurrentThread()) {} 18 19 void VsyncParent::UpdateVsyncDispatcher( 20 const RefPtr<VsyncDispatcher>& aVsyncDispatcher) { 21 if (aVsyncDispatcher == mVsyncDispatcher) { 22 return; 23 } 24 25 if (mObservingVsync && mVsyncDispatcher) { 26 mVsyncDispatcher->RemoveVsyncObserver(this); 27 } 28 mVsyncDispatcher = aVsyncDispatcher; 29 if (mObservingVsync) { 30 mVsyncDispatcher->AddVsyncObserver(this); 31 } 32 } 33 34 void VsyncParent::NotifyVsync(const VsyncEvent& aVsync) { 35 if (IsOnInitialThread()) { 36 DispatchVsyncEvent(aVsync); 37 return; 38 } 39 40 // Called on hardware vsync thread. We should post to current ipc thread. 41 nsCOMPtr<nsIRunnable> vsyncEvent = NewRunnableMethod<VsyncEvent>( 42 "dom::VsyncParent::DispatchVsyncEvent", this, 43 &VsyncParent::DispatchVsyncEvent, aVsync); 44 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToThreadQueue( 45 vsyncEvent.forget(), mInitialThread, EventQueuePriority::Vsync)); 46 } 47 48 void VsyncParent::DispatchVsyncEvent(const VsyncEvent& aVsync) { 49 AssertIsOnInitialThread(); 50 51 // If we call NotifyVsync() when we handle ActorDestroy() message, we might 52 // still call DispatchVsyncEvent(). 53 // Similarly, we might also receive RecvUnobserveVsync() when call 54 // NotifyVsync(). We use mObservingVsync and mDestroyed flags to skip this 55 // notification. 56 if (mObservingVsync && !mDestroyed) { 57 TimeDuration vsyncRate = mVsyncDispatcher->GetVsyncRate(); 58 (void)SendNotify(aVsync, vsyncRate.ToMilliseconds()); 59 } 60 } 61 62 mozilla::ipc::IPCResult VsyncParent::RecvObserve() { 63 AssertIsOnInitialThread(); 64 if (!mObservingVsync) { 65 if (mVsyncDispatcher) { 66 mVsyncDispatcher->AddVsyncObserver(this); 67 } 68 mObservingVsync = true; 69 return IPC_OK(); 70 } 71 return IPC_FAIL_NO_REASON(this); 72 } 73 74 mozilla::ipc::IPCResult VsyncParent::RecvUnobserve() { 75 AssertIsOnInitialThread(); 76 if (mObservingVsync) { 77 if (mVsyncDispatcher) { 78 mVsyncDispatcher->RemoveVsyncObserver(this); 79 } 80 mObservingVsync = false; 81 return IPC_OK(); 82 } 83 return IPC_FAIL_NO_REASON(this); 84 } 85 86 void VsyncParent::ActorDestroy(ActorDestroyReason aActorDestroyReason) { 87 MOZ_ASSERT(!mDestroyed); 88 AssertIsOnInitialThread(); 89 if (mObservingVsync && mVsyncDispatcher) { 90 mVsyncDispatcher->RemoveVsyncObserver(this); 91 } 92 mVsyncDispatcher = nullptr; 93 mDestroyed = true; 94 } 95 96 bool VsyncParent::IsOnInitialThread() { 97 return NS_GetCurrentThread() == mInitialThread; 98 } 99 100 void VsyncParent::AssertIsOnInitialThread() { MOZ_ASSERT(IsOnInitialThread()); } 101 102 } // namespace mozilla::dom