Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=99: */
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 :
10 : namespace mozilla {
11 : namespace gfx {
12 :
13 0 : VsyncBridgeChild::VsyncBridgeChild(RefPtr<VsyncIOThreadHolder> aThread, const uint64_t& aProcessToken)
14 : : mThread(aThread),
15 : mLoop(nullptr),
16 0 : mProcessToken(aProcessToken)
17 : {
18 0 : }
19 :
20 0 : VsyncBridgeChild::~VsyncBridgeChild()
21 : {
22 0 : }
23 :
24 : /* static */ RefPtr<VsyncBridgeChild>
25 0 : VsyncBridgeChild::Create(RefPtr<VsyncIOThreadHolder> aThread,
26 : const uint64_t& aProcessToken,
27 : Endpoint<PVsyncBridgeChild>&& aEndpoint)
28 : {
29 0 : RefPtr<VsyncBridgeChild> child = new VsyncBridgeChild(aThread, aProcessToken);
30 :
31 0 : RefPtr<nsIRunnable> task = NewRunnableMethod<Endpoint<PVsyncBridgeChild>&&>(
32 : "gfx::VsyncBridgeChild::Open",
33 : child,
34 : &VsyncBridgeChild::Open,
35 0 : Move(aEndpoint));
36 0 : aThread->GetThread()->Dispatch(task.forget(), nsIThread::DISPATCH_NORMAL);
37 :
38 0 : return child;
39 : }
40 :
41 : void
42 0 : VsyncBridgeChild::Open(Endpoint<PVsyncBridgeChild>&& aEndpoint)
43 : {
44 0 : if (!aEndpoint.Bind(this)) {
45 : // The GPU Process Manager might be gone if we receive ActorDestroy very
46 : // late in shutdown.
47 0 : if (GPUProcessManager* gpm = GPUProcessManager::Get())
48 0 : gpm->NotifyRemoteActorDestroyed(mProcessToken);
49 0 : return;
50 : }
51 :
52 0 : mLoop = MessageLoop::current();
53 :
54 : // Last reference is freed in DeallocPVsyncBridgeChild.
55 0 : AddRef();
56 : }
57 :
58 0 : class NotifyVsyncTask : public Runnable
59 : {
60 : public:
61 0 : NotifyVsyncTask(RefPtr<VsyncBridgeChild> aVsyncBridge,
62 : TimeStamp aTimeStamp,
63 : const uint64_t& aLayersId)
64 0 : : Runnable("gfx::NotifyVsyncTask")
65 : , mVsyncBridge(aVsyncBridge)
66 : , mTimeStamp(aTimeStamp)
67 0 : , mLayersId(aLayersId)
68 0 : {}
69 :
70 0 : NS_IMETHOD Run() override {
71 0 : mVsyncBridge->NotifyVsyncImpl(mTimeStamp, mLayersId);
72 0 : return NS_OK;
73 : }
74 :
75 : private:
76 : RefPtr<VsyncBridgeChild> mVsyncBridge;
77 : TimeStamp mTimeStamp;
78 : uint64_t mLayersId;
79 : };
80 :
81 : bool
82 0 : VsyncBridgeChild::IsOnVsyncIOThread() const
83 : {
84 0 : return MessageLoop::current() == mLoop;
85 : }
86 :
87 : void
88 0 : VsyncBridgeChild::NotifyVsync(TimeStamp aTimeStamp, const uint64_t& aLayersId)
89 : {
90 : // This should be on the Vsync thread (not the Vsync I/O thread).
91 0 : MOZ_ASSERT(!IsOnVsyncIOThread());
92 :
93 0 : RefPtr<NotifyVsyncTask> task = new NotifyVsyncTask(this, aTimeStamp, aLayersId);
94 0 : mLoop->PostTask(task.forget());
95 0 : }
96 :
97 : void
98 0 : VsyncBridgeChild::NotifyVsyncImpl(TimeStamp aTimeStamp, const uint64_t& aLayersId)
99 : {
100 : // This should be on the Vsync I/O thread.
101 0 : MOZ_ASSERT(IsOnVsyncIOThread());
102 :
103 0 : if (!mProcessToken) {
104 0 : return;
105 : }
106 0 : SendNotifyVsync(aTimeStamp, aLayersId);
107 : }
108 :
109 : void
110 0 : VsyncBridgeChild::Close()
111 : {
112 0 : if (!IsOnVsyncIOThread()) {
113 0 : mLoop->PostTask(NewRunnableMethod(
114 0 : "gfx::VsyncBridgeChild::Close", this, &VsyncBridgeChild::Close));
115 0 : return;
116 : }
117 :
118 : // We clear mProcessToken when the channel is closed.
119 0 : if (!mProcessToken) {
120 0 : return;
121 : }
122 :
123 : // Clear the process token so we don't notify the GPUProcessManager. It already
124 : // knows we're closed since it manually called Close, and in fact the GPM could
125 : // have already been destroyed during shutdown.
126 0 : mProcessToken = 0;
127 :
128 : // Close the underlying IPC channel.
129 0 : PVsyncBridgeChild::Close();
130 : }
131 :
132 : void
133 0 : VsyncBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
134 : {
135 0 : if (mProcessToken) {
136 0 : GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken);
137 0 : mProcessToken = 0;
138 : }
139 0 : }
140 :
141 : void
142 0 : VsyncBridgeChild::DeallocPVsyncBridgeChild()
143 : {
144 0 : Release();
145 0 : }
146 :
147 : void
148 0 : VsyncBridgeChild::ProcessingError(Result aCode, const char* aReason)
149 : {
150 0 : MOZ_RELEASE_ASSERT(aCode == MsgDropped, "Processing error in VsyncBridgeChild");
151 0 : }
152 :
153 : void
154 0 : VsyncBridgeChild::HandleFatalError(const char* aName, const char* aMsg) const
155 : {
156 0 : dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aName, aMsg, OtherPid());
157 0 : }
158 :
159 : } // namespace gfx
160 : } // namespace mozilla
|