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
);
45 class NotifyVsyncTask
: public Runnable
{
47 NotifyVsyncTask(RefPtr
<VsyncBridgeChild
> aVsyncBridge
,
48 const VsyncEvent
& aVsync
, const layers::LayersId
& aLayersId
)
49 : Runnable("gfx::NotifyVsyncTask"),
50 mVsyncBridge(aVsyncBridge
),
52 mLayersId(aLayersId
) {}
54 NS_IMETHOD
Run() override
{
55 mVsyncBridge
->NotifyVsyncImpl(mVsync
, mLayersId
);
60 RefPtr
<VsyncBridgeChild
> mVsyncBridge
;
62 layers::LayersId mLayersId
;
65 bool VsyncBridgeChild::IsOnVsyncIOThread() const {
66 return mThread
->IsOnCurrentThread();
69 void VsyncBridgeChild::NotifyVsync(const VsyncEvent
& aVsync
,
70 const layers::LayersId
& aLayersId
) {
71 // This should be on the Vsync thread (not the Vsync I/O thread).
72 MOZ_ASSERT(!IsOnVsyncIOThread());
74 RefPtr
<NotifyVsyncTask
> task
= new NotifyVsyncTask(this, aVsync
, aLayersId
);
75 mThread
->Dispatch(task
.forget());
78 void VsyncBridgeChild::NotifyVsyncImpl(const VsyncEvent
& aVsync
,
79 const layers::LayersId
& aLayersId
) {
80 // This should be on the Vsync I/O thread.
81 MOZ_ASSERT(IsOnVsyncIOThread());
86 SendNotifyVsync(aVsync
, aLayersId
);
89 void VsyncBridgeChild::Close() {
90 if (!IsOnVsyncIOThread()) {
91 mThread
->Dispatch(NewRunnableMethod("gfx::VsyncBridgeChild::Close", this,
92 &VsyncBridgeChild::Close
));
96 // We clear mProcessToken when the channel is closed.
101 // Clear the process token so we don't notify the GPUProcessManager. It
102 // already knows we're closed since it manually called Close, and in fact the
103 // GPM could have already been destroyed during shutdown.
106 // Close the underlying IPC channel.
107 PVsyncBridgeChild::Close();
110 void VsyncBridgeChild::ActorDestroy(ActorDestroyReason aWhy
) {
112 GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken
);
117 void VsyncBridgeChild::ProcessingError(Result aCode
, const char* aReason
) {
118 MOZ_RELEASE_ASSERT(aCode
== MsgDropped
,
119 "Processing error in VsyncBridgeChild");
122 void VsyncBridgeChild::HandleFatalError(const char* aMsg
) {
123 dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg
, OtherPid());
127 } // namespace mozilla