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 #include "VsyncBridgeChild.h"
7 #include "VsyncIOThreadHolder.h"
8 #include "mozilla/dom/ContentChild.h"
9 #include "mozilla/gfx/GPUProcessManager.h"
10
11 namespace mozilla {
12 namespace gfx {
13
VsyncBridgeChild(RefPtr<VsyncIOThreadHolder> aThread,const uint64_t & aProcessToken)14 VsyncBridgeChild::VsyncBridgeChild(RefPtr<VsyncIOThreadHolder> aThread,
15 const uint64_t& aProcessToken)
16 : mThread(aThread), mProcessToken(aProcessToken) {}
17
18 VsyncBridgeChild::~VsyncBridgeChild() = default;
19
20 /* static */
Create(RefPtr<VsyncIOThreadHolder> aThread,const uint64_t & aProcessToken,Endpoint<PVsyncBridgeChild> && aEndpoint)21 RefPtr<VsyncBridgeChild> VsyncBridgeChild::Create(
22 RefPtr<VsyncIOThreadHolder> aThread, const uint64_t& aProcessToken,
23 Endpoint<PVsyncBridgeChild>&& aEndpoint) {
24 RefPtr<VsyncBridgeChild> child = new VsyncBridgeChild(aThread, aProcessToken);
25
26 RefPtr<nsIRunnable> task = NewRunnableMethod<Endpoint<PVsyncBridgeChild>&&>(
27 "gfx::VsyncBridgeChild::Open", child, &VsyncBridgeChild::Open,
28 std::move(aEndpoint));
29 aThread->GetThread()->Dispatch(task.forget(), nsIThread::DISPATCH_NORMAL);
30
31 return child;
32 }
33
Open(Endpoint<PVsyncBridgeChild> && aEndpoint)34 void VsyncBridgeChild::Open(Endpoint<PVsyncBridgeChild>&& aEndpoint) {
35 if (!aEndpoint.Bind(this)) {
36 // The GPU Process Manager might be gone if we receive ActorDestroy very
37 // late in shutdown.
38 if (GPUProcessManager* gpm = GPUProcessManager::Get())
39 gpm->NotifyRemoteActorDestroyed(mProcessToken);
40 return;
41 }
42
43 // Last reference is freed in DeallocPVsyncBridgeChild.
44 AddRef();
45 }
46
47 class NotifyVsyncTask : public Runnable {
48 public:
NotifyVsyncTask(RefPtr<VsyncBridgeChild> aVsyncBridge,const VsyncEvent & aVsync,const layers::LayersId & aLayersId)49 NotifyVsyncTask(RefPtr<VsyncBridgeChild> aVsyncBridge,
50 const VsyncEvent& aVsync, const layers::LayersId& aLayersId)
51 : Runnable("gfx::NotifyVsyncTask"),
52 mVsyncBridge(aVsyncBridge),
53 mVsync(aVsync),
54 mLayersId(aLayersId) {}
55
Run()56 NS_IMETHOD Run() override {
57 mVsyncBridge->NotifyVsyncImpl(mVsync, mLayersId);
58 return NS_OK;
59 }
60
61 private:
62 RefPtr<VsyncBridgeChild> mVsyncBridge;
63 VsyncEvent mVsync;
64 layers::LayersId mLayersId;
65 };
66
IsOnVsyncIOThread() const67 bool VsyncBridgeChild::IsOnVsyncIOThread() const {
68 return mThread->IsOnCurrentThread();
69 }
70
NotifyVsync(const VsyncEvent & aVsync,const layers::LayersId & aLayersId)71 void VsyncBridgeChild::NotifyVsync(const VsyncEvent& aVsync,
72 const layers::LayersId& aLayersId) {
73 // This should be on the Vsync thread (not the Vsync I/O thread).
74 MOZ_ASSERT(!IsOnVsyncIOThread());
75
76 RefPtr<NotifyVsyncTask> task = new NotifyVsyncTask(this, aVsync, aLayersId);
77 mThread->Dispatch(task.forget());
78 }
79
NotifyVsyncImpl(const VsyncEvent & aVsync,const layers::LayersId & aLayersId)80 void VsyncBridgeChild::NotifyVsyncImpl(const VsyncEvent& aVsync,
81 const layers::LayersId& aLayersId) {
82 // This should be on the Vsync I/O thread.
83 MOZ_ASSERT(IsOnVsyncIOThread());
84
85 if (!mProcessToken) {
86 return;
87 }
88 SendNotifyVsync(aVsync, aLayersId);
89 }
90
Close()91 void VsyncBridgeChild::Close() {
92 if (!IsOnVsyncIOThread()) {
93 mThread->Dispatch(NewRunnableMethod("gfx::VsyncBridgeChild::Close", this,
94 &VsyncBridgeChild::Close));
95 return;
96 }
97
98 // We clear mProcessToken when the channel is closed.
99 if (!mProcessToken) {
100 return;
101 }
102
103 // Clear the process token so we don't notify the GPUProcessManager. It
104 // already knows we're closed since it manually called Close, and in fact the
105 // GPM could have already been destroyed during shutdown.
106 mProcessToken = 0;
107
108 // Close the underlying IPC channel.
109 PVsyncBridgeChild::Close();
110 }
111
ActorDestroy(ActorDestroyReason aWhy)112 void VsyncBridgeChild::ActorDestroy(ActorDestroyReason aWhy) {
113 if (mProcessToken) {
114 GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken);
115 mProcessToken = 0;
116 }
117 }
118
ActorDealloc()119 void VsyncBridgeChild::ActorDealloc() { Release(); }
120
ProcessingError(Result aCode,const char * aReason)121 void VsyncBridgeChild::ProcessingError(Result aCode, const char* aReason) {
122 MOZ_RELEASE_ASSERT(aCode == MsgDropped,
123 "Processing error in VsyncBridgeChild");
124 }
125
HandleFatalError(const char * aMsg) const126 void VsyncBridgeChild::HandleFatalError(const char* aMsg) const {
127 dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherPid());
128 }
129
130 } // namespace gfx
131 } // namespace mozilla
132