Bug 1738971 - Part 4. Add VsyncWorkerChild to get vsync events. r=gfx-reviewers,dom-worker-reviewers,jgilbert,smaug

requestAnimationFrame callbacks are supposed to be synchronized with the
vsync events into the refresh driver for the window. This patch adds an
IPDL actor implementation for workers to subscribe as necessary to vsync
events.

Differential Revision: https://phabricator.services.mozilla.com/D130265
This commit is contained in:
Andrew Osmond 2021-12-10 02:57:51 +00:00
parent c439ab6cd3
commit ddca5b5abd
4 changed files with 125 additions and 0 deletions

View File

@ -0,0 +1,67 @@
/* -*- 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 "VsyncWorkerChild.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRef.h"
#include "mozilla/dom/WorkerScope.h"
namespace mozilla::dom {
VsyncWorkerChild::VsyncWorkerChild() = default;
VsyncWorkerChild::~VsyncWorkerChild() = default;
bool VsyncWorkerChild::Initialize(WorkerPrivate* aWorkerPrivate) {
MOZ_ASSERT(aWorkerPrivate);
MOZ_ASSERT(!mWorkerRef);
mWorkerRef =
IPCWorkerRef::Create(aWorkerPrivate, "VsyncWorkerChild",
[self = RefPtr{this}]() { self->Destroy(); });
return !!mWorkerRef;
}
void VsyncWorkerChild::Destroy() {
MOZ_ASSERT_IF(!CanSend(), !mWorkerRef);
MOZ_ASSERT_IF(!CanSend(), !mObserving);
Send__delete__(this);
MOZ_ASSERT(!mWorkerRef);
MOZ_ASSERT(!mObserving);
}
void VsyncWorkerChild::TryObserve() {
if (CanSend() && !mObserving) {
mObserving = SendObserve();
}
}
void VsyncWorkerChild::TryUnobserve() {
if (CanSend() && mObserving) {
mObserving = !SendUnobserve();
}
}
mozilla::ipc::IPCResult VsyncWorkerChild::RecvNotify(const VsyncEvent& aVsync,
const float& aVsyncRate) {
// For MOZ_CAN_RUN_SCRIPT_BOUNDARY purposes: We know IPDL is explicitly
// keeping our actor alive until it is done processing the messages. We know
// that the WorkerGlobalScope callee is responsible keeping itself alive
// during the OnVsync callback.
WorkerPrivate* workerPrivate = mWorkerRef->Private();
WorkerGlobalScope* scope = workerPrivate->GlobalScope();
if (scope) {
scope->OnVsync(aVsync);
}
return IPC_OK();
}
void VsyncWorkerChild::ActorDestroy(ActorDestroyReason aActorDestroyReason) {
mWorkerRef = nullptr;
mObserving = false;
}
} // namespace mozilla::dom

View File

@ -0,0 +1,52 @@
/* -*- 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/. */
#ifndef mozilla_dom_ipc_VsyncWorkerChild_h
#define mozilla_dom_ipc_VsyncWorkerChild_h
#include "mozilla/dom/VsyncChild.h"
#include "mozilla/RefPtr.h"
#include "nsISupportsImpl.h"
namespace mozilla::dom {
class DedicatedWorkerGlobalScope;
class IPCWorkerRef;
class WorkerPrivate;
// The PVsyncWorkerChild actor receives a vsync event from the main process and
// delivers it to the child process. This is specific for workers which wish to
// subscribe to vsync events to drive requestAnimationFrame callbacks.
class VsyncWorkerChild final : public VsyncChild {
NS_INLINE_DECL_REFCOUNTING(VsyncWorkerChild, override)
friend class PVsyncChild;
public:
VsyncWorkerChild();
bool Initialize(WorkerPrivate* aWorkerPrivate);
void Destroy();
void TryObserve();
void TryUnobserve();
private:
~VsyncWorkerChild() override;
mozilla::ipc::IPCResult RecvNotify(const VsyncEvent& aVsync,
const float& aVsyncRate) override;
void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
RefPtr<IPCWorkerRef> mWorkerRef;
bool mObserving = false;
};
} // namespace mozilla::dom
#endif // mozilla_dom_ipc_VsyncWorkerChild_h

View File

@ -81,6 +81,7 @@ EXPORTS.mozilla.dom += [
"VsyncChild.h",
"VsyncMainChild.h",
"VsyncParent.h",
"VsyncWorkerChild.h",
"WindowGlobalActor.h",
"WindowGlobalChild.h",
"WindowGlobalParent.h",
@ -145,6 +146,7 @@ SOURCES += [
"ProcessHangMonitor.cpp",
"VsyncMainChild.cpp",
"VsyncParent.cpp",
"VsyncWorkerChild.cpp",
]
PREPROCESSED_IPDL_SOURCES += [

View File

@ -34,6 +34,7 @@ class nsISerialEventTarget;
namespace mozilla {
class ErrorResult;
struct VsyncEvent;
namespace extensions {
@ -303,6 +304,9 @@ class WorkerGlobalScope : public WorkerGlobalScopeBase,
virtual void OnDocumentVisible(bool aVisible) {}
MOZ_CAN_RUN_SCRIPT_BOUNDARY
virtual void OnVsync(const VsyncEvent& aVsync) {}
protected:
~WorkerGlobalScope();