diff options
Diffstat (limited to 'gfx/ipc/VsyncBridgeChild.cpp')
-rw-r--r-- | gfx/ipc/VsyncBridgeChild.cpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/gfx/ipc/VsyncBridgeChild.cpp b/gfx/ipc/VsyncBridgeChild.cpp new file mode 100644 index 0000000000..044a24f320 --- /dev/null +++ b/gfx/ipc/VsyncBridgeChild.cpp @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "VsyncBridgeChild.h" +#include "VsyncIOThreadHolder.h" +#include "mozilla/dom/ContentChild.h" +#include "mozilla/gfx/GPUProcessManager.h" +#include "mozilla/ipc/Endpoint.h" + +namespace mozilla { +namespace gfx { + +VsyncBridgeChild::VsyncBridgeChild(RefPtr<VsyncIOThreadHolder> aThread, + const uint64_t& aProcessToken) + : mThread(aThread), mProcessToken(aProcessToken) {} + +VsyncBridgeChild::~VsyncBridgeChild() = default; + +/* static */ +RefPtr<VsyncBridgeChild> VsyncBridgeChild::Create( + RefPtr<VsyncIOThreadHolder> aThread, const uint64_t& aProcessToken, + Endpoint<PVsyncBridgeChild>&& aEndpoint) { + RefPtr<VsyncBridgeChild> child = new VsyncBridgeChild(aThread, aProcessToken); + + RefPtr<nsIRunnable> task = NewRunnableMethod<Endpoint<PVsyncBridgeChild>&&>( + "gfx::VsyncBridgeChild::Open", child, &VsyncBridgeChild::Open, + std::move(aEndpoint)); + aThread->GetThread()->Dispatch(task.forget(), nsIThread::DISPATCH_NORMAL); + + return child; +} + +void VsyncBridgeChild::Open(Endpoint<PVsyncBridgeChild>&& aEndpoint) { + if (!aEndpoint.Bind(this)) { + // The GPU Process Manager might be gone if we receive ActorDestroy very + // late in shutdown. + if (GPUProcessManager* gpm = GPUProcessManager::Get()) + gpm->NotifyRemoteActorDestroyed(mProcessToken); + return; + } +} + +class NotifyVsyncTask : public Runnable { + public: + NotifyVsyncTask(RefPtr<VsyncBridgeChild> aVsyncBridge, + const VsyncEvent& aVsync, const layers::LayersId& aLayersId) + : Runnable("gfx::NotifyVsyncTask"), + mVsyncBridge(aVsyncBridge), + mVsync(aVsync), + mLayersId(aLayersId) {} + + NS_IMETHOD Run() override { + mVsyncBridge->NotifyVsyncImpl(mVsync, mLayersId); + return NS_OK; + } + + private: + RefPtr<VsyncBridgeChild> mVsyncBridge; + VsyncEvent mVsync; + layers::LayersId mLayersId; +}; + +bool VsyncBridgeChild::IsOnVsyncIOThread() const { + return mThread->IsOnCurrentThread(); +} + +void VsyncBridgeChild::NotifyVsync(const VsyncEvent& aVsync, + const layers::LayersId& aLayersId) { + // This should be on the Vsync thread (not the Vsync I/O thread). + MOZ_ASSERT(!IsOnVsyncIOThread()); + + RefPtr<NotifyVsyncTask> task = new NotifyVsyncTask(this, aVsync, aLayersId); + mThread->Dispatch(task.forget()); +} + +void VsyncBridgeChild::NotifyVsyncImpl(const VsyncEvent& aVsync, + const layers::LayersId& aLayersId) { + // This should be on the Vsync I/O thread. + MOZ_ASSERT(IsOnVsyncIOThread()); + + if (!mProcessToken) { + return; + } + SendNotifyVsync(aVsync, aLayersId); +} + +void VsyncBridgeChild::Close() { + if (!IsOnVsyncIOThread()) { + mThread->Dispatch(NewRunnableMethod("gfx::VsyncBridgeChild::Close", this, + &VsyncBridgeChild::Close)); + return; + } + + // We clear mProcessToken when the channel is closed. + if (!mProcessToken) { + return; + } + + // Clear the process token so we don't notify the GPUProcessManager. It + // already knows we're closed since it manually called Close, and in fact the + // GPM could have already been destroyed during shutdown. + mProcessToken = 0; + + // Close the underlying IPC channel. + PVsyncBridgeChild::Close(); +} + +void VsyncBridgeChild::ActorDestroy(ActorDestroyReason aWhy) { + if (mProcessToken) { + GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken); + mProcessToken = 0; + } +} + +void VsyncBridgeChild::ProcessingError(Result aCode, const char* aReason) { + MOZ_RELEASE_ASSERT(aCode == MsgDropped, + "Processing error in VsyncBridgeChild"); +} + +void VsyncBridgeChild::HandleFatalError(const char* aMsg) { + dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aMsg, OtherPid()); +} + +} // namespace gfx +} // namespace mozilla |