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 #include "mozilla/ipc/Endpoint.h"
15 VsyncBridgeChild::VsyncBridgeChild(RefPtr
<VsyncIOThreadHolder
> aThread
,
16 const uint64_t& aProcessToken
)
17 : mThread(aThread
), mProcessToken(aProcessToken
) {}
19 VsyncBridgeChild::~VsyncBridgeChild() = default;
22 RefPtr
<VsyncBridgeChild
> VsyncBridgeChild::Create(
23 RefPtr
<VsyncIOThreadHolder
> aThread
, const uint64_t& aProcessToken
,
24 Endpoint
<PVsyncBridgeChild
>&& aEndpoint
) {
25 RefPtr
<VsyncBridgeChild
> child
= new VsyncBridgeChild(aThread
, aProcessToken
);
27 RefPtr
<nsIRunnable
> task
= NewRunnableMethod
<Endpoint
<PVsyncBridgeChild
>&&>(
28 "gfx::VsyncBridgeChild::Open", child
, &VsyncBridgeChild::Open
,
29 std::move(aEndpoint
));
30 aThread
->GetThread()->Dispatch(task
.forget(), nsIThread::DISPATCH_NORMAL
);
35 void VsyncBridgeChild::Open(Endpoint
<PVsyncBridgeChild
>&& aEndpoint
) {
36 if (!aEndpoint
.Bind(this)) {
37 // The GPU Process Manager might be gone if we receive ActorDestroy very
39 if (GPUProcessManager
* gpm
= GPUProcessManager::Get())
40 gpm
->NotifyRemoteActorDestroyed(mProcessToken
);
44 // Last reference is freed in DeallocPVsyncBridgeChild.
48 class NotifyVsyncTask
: public Runnable
{
50 NotifyVsyncTask(RefPtr
<VsyncBridgeChild
> aVsyncBridge
,
51 const VsyncEvent
& aVsync
, const layers::LayersId
& aLayersId
)
52 : Runnable("gfx::NotifyVsyncTask"),
53 mVsyncBridge(aVsyncBridge
),
55 mLayersId(aLayersId
) {}
57 NS_IMETHOD
Run() override
{
58 mVsyncBridge
->NotifyVsyncImpl(mVsync
, mLayersId
);
63 RefPtr
<VsyncBridgeChild
> mVsyncBridge
;
65 layers::LayersId mLayersId
;
68 bool VsyncBridgeChild::IsOnVsyncIOThread() const {
69 return mThread
->IsOnCurrentThread();
72 void VsyncBridgeChild::NotifyVsync(const VsyncEvent
& aVsync
,
73 const layers::LayersId
& aLayersId
) {
74 // This should be on the Vsync thread (not the Vsync I/O thread).
75 MOZ_ASSERT(!IsOnVsyncIOThread());
77 RefPtr
<NotifyVsyncTask
> task
= new NotifyVsyncTask(this, aVsync
, aLayersId
);
78 mThread
->Dispatch(task
.forget());
81 void VsyncBridgeChild::NotifyVsyncImpl(const VsyncEvent
& aVsync
,
82 const layers::LayersId
& aLayersId
) {
83 // This should be on the Vsync I/O thread.
84 MOZ_ASSERT(IsOnVsyncIOThread());
89 SendNotifyVsync(aVsync
, aLayersId
);
92 void VsyncBridgeChild::Close() {
93 if (!IsOnVsyncIOThread()) {
94 mThread
->Dispatch(NewRunnableMethod("gfx::VsyncBridgeChild::Close", this,
95 &VsyncBridgeChild::Close
));
99 // We clear mProcessToken when the channel is closed.
100 if (!mProcessToken
) {
104 // Clear the process token so we don't notify the GPUProcessManager. It
105 // already knows we're closed since it manually called Close, and in fact the
106 // GPM could have already been destroyed during shutdown.
109 // Close the underlying IPC channel.
110 PVsyncBridgeChild::Close();
113 void VsyncBridgeChild::ActorDestroy(ActorDestroyReason aWhy
) {
115 GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken
);
120 void VsyncBridgeChild::ActorDealloc() { Release(); }
122 void VsyncBridgeChild::ProcessingError(Result aCode
, const char* aReason
) {
123 MOZ_RELEASE_ASSERT(aCode
== MsgDropped
,
124 "Processing error in VsyncBridgeChild");
127 void VsyncBridgeChild::HandleFatalError(const char* aMsg
) const {
128 dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg
, OtherPid());
132 } // namespace mozilla