mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Backed out changeset 3a9dce735340 (bug 1645528) for causing crashes with nsRefreshDriver CLOSED TREE
This commit is contained in:
parent
77dfbe7938
commit
c5213774a6
@ -14,7 +14,6 @@
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include "BackgroundChild.h"
|
||||
#include "BrowserParent.h"
|
||||
#include "ClientLayerManager.h"
|
||||
#include "ContentChild.h"
|
||||
@ -75,7 +74,6 @@
|
||||
#include "mozilla/gfx/Matrix.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
#include "mozilla/layers/APZCCallbackHelper.h"
|
||||
#include "mozilla/layers/APZCTreeManagerChild.h"
|
||||
@ -144,10 +142,6 @@
|
||||
# include "mozilla/plugins/PluginWidgetChild.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WAYLAND
|
||||
# include "nsAppRunner.h"
|
||||
#endif
|
||||
|
||||
#ifdef NS_PRINTING
|
||||
# include "nsIPrintSession.h"
|
||||
# include "nsIPrintSettings.h"
|
||||
@ -320,7 +314,6 @@ BrowserChild::BrowserChild(ContentChild* aManager, const TabId& aTabId,
|
||||
mDidFakeShow(false),
|
||||
mTriedBrowserInit(false),
|
||||
mOrientation(hal::eScreenOrientation_PortraitPrimary),
|
||||
mVsyncChild(nullptr),
|
||||
mIgnoreKeyPressEvent(false),
|
||||
mHasValidInnerSize(false),
|
||||
mDestroyed(false),
|
||||
@ -557,8 +550,6 @@ nsresult BrowserChild::Init(mozIDOMWindowProxy* aParent,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#endif
|
||||
|
||||
InitVsyncChild();
|
||||
|
||||
// We've all set up, make sure our visibility state is consistent. This is
|
||||
// important for OOP iframes, which start off as hidden.
|
||||
UpdateVisibility();
|
||||
@ -566,20 +557,6 @@ nsresult BrowserChild::Init(mozIDOMWindowProxy* aParent,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void BrowserChild::InitVsyncChild() {
|
||||
#if defined(MOZ_WAYLAND)
|
||||
if (!IsWaylandDisabled()) {
|
||||
PVsyncChild* actor = SendPVsyncConstructor();
|
||||
mVsyncChild = static_cast<VsyncChild*>(actor);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
PBackgroundChild* actorChild =
|
||||
BackgroundChild::GetOrCreateForCurrentThread();
|
||||
mVsyncChild = static_cast<VsyncChild*>(actorChild->SendPVsyncConstructor());
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserChild::NotifyTabContextUpdated() {
|
||||
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
|
||||
MOZ_ASSERT(docShell);
|
||||
@ -2166,23 +2143,6 @@ bool BrowserChild::DeallocPFilePickerChild(PFilePickerChild* actor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
PVsyncChild* BrowserChild::AllocPVsyncChild() {
|
||||
RefPtr<dom::VsyncChild> actor = new VsyncChild();
|
||||
// There still has one ref-count after return, and it will be released in
|
||||
// DeallocPVsyncChild().
|
||||
return actor.forget().take();
|
||||
}
|
||||
|
||||
bool BrowserChild::DeallocPVsyncChild(PVsyncChild* aActor) {
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
// This actor already has one ref-count. Please check AllocPVsyncChild().
|
||||
RefPtr<VsyncChild> actor = dont_AddRef(static_cast<VsyncChild*>(aActor));
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<VsyncChild> BrowserChild::GetVsyncChild() { return mVsyncChild; }
|
||||
|
||||
mozilla::ipc::IPCResult BrowserChild::RecvActivateFrameEvent(
|
||||
const nsString& aType, const bool& capture) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation());
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "mozilla/dom/CoalescedMouseData.h"
|
||||
#include "mozilla/dom/CoalescedWheelData.h"
|
||||
#include "mozilla/dom/MessageManagerCallback.h"
|
||||
#include "mozilla/dom/VsyncChild.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
@ -437,12 +436,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
|
||||
PFilePickerChild* AllocPFilePickerChild(const nsString& aTitle,
|
||||
const int16_t& aMode);
|
||||
|
||||
virtual PVsyncChild* AllocPVsyncChild();
|
||||
|
||||
virtual bool DeallocPVsyncChild(PVsyncChild* aActor);
|
||||
|
||||
RefPtr<VsyncChild> GetVsyncChild();
|
||||
|
||||
bool DeallocPFilePickerChild(PFilePickerChild* aActor);
|
||||
|
||||
nsIWebNavigation* WebNavigation() const { return mWebNav; }
|
||||
@ -754,8 +747,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
|
||||
const mozilla::layers::CompositorOptions& aCompositorOptions);
|
||||
void InitAPZState();
|
||||
|
||||
void InitVsyncChild();
|
||||
|
||||
void DestroyWindow();
|
||||
|
||||
void ApplyParentShowInfo(const ParentShowInfo&);
|
||||
@ -823,8 +814,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
|
||||
bool mTriedBrowserInit;
|
||||
hal::ScreenOrientation mOrientation;
|
||||
|
||||
RefPtr<VsyncChild> mVsyncChild;
|
||||
|
||||
bool mIgnoreKeyPressEvent;
|
||||
RefPtr<APZEventState> mAPZEventState;
|
||||
SetAllowedTouchBehaviorCallback mSetAllowedTouchBehaviorCallback;
|
||||
|
@ -129,7 +129,6 @@
|
||||
#include "mozilla/dom/CrashReport.h"
|
||||
#include "nsISecureBrowserUI.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "VsyncSource.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include "mozilla/plugins/PluginWidgetParent.h"
|
||||
@ -225,7 +224,6 @@ BrowserParent::BrowserParent(ContentParent* aManager, const TabId& aTabId,
|
||||
mCustomCursorHotspotX(0),
|
||||
mCustomCursorHotspotY(0),
|
||||
mVerifyDropLinks{},
|
||||
mVsyncParent(nullptr),
|
||||
mDocShellIsActive(false),
|
||||
mMarkedDestroying(false),
|
||||
mIsDestroyed(false),
|
||||
@ -565,8 +563,6 @@ void BrowserParent::SetOwnerElement(Element* aElement) {
|
||||
mBrowsingContext->SetEmbedderElement(mFrameElement);
|
||||
}
|
||||
|
||||
UpdateVsyncParentVsyncSource();
|
||||
|
||||
VisitChildren([aElement](BrowserBridgeParent* aBrowser) {
|
||||
if (auto* browserParent = aBrowser->GetBrowserParent()) {
|
||||
browserParent->SetOwnerElement(aElement);
|
||||
@ -1350,28 +1346,6 @@ IPCResult BrowserParent::RecvNewWindowGlobal(
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
PVsyncParent* BrowserParent::AllocPVsyncParent() {
|
||||
MOZ_ASSERT(!mVsyncParent);
|
||||
mVsyncParent = new VsyncParent();
|
||||
UpdateVsyncParentVsyncSource();
|
||||
return mVsyncParent.get();
|
||||
}
|
||||
|
||||
bool BrowserParent::DeallocPVsyncParent(PVsyncParent* aActor) {
|
||||
mVsyncParent = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
void BrowserParent::UpdateVsyncParentVsyncSource() {
|
||||
if (!mVsyncParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsCOMPtr<nsIWidget> widget = GetWidget()) {
|
||||
mVsyncParent->UpdateVsyncSource(widget->GetVsyncSource());
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserParent::SendMouseEvent(const nsAString& aType, float aX, float aY,
|
||||
int32_t aButton, int32_t aClickCount,
|
||||
int32_t aModifiers) {
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "mozilla/dom/BrowserBridgeParent.h"
|
||||
#include "mozilla/dom/PBrowserParent.h"
|
||||
#include "mozilla/dom/TabContext.h"
|
||||
#include "mozilla/dom/VsyncParent.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
#include "mozilla/layout/RemoteLayerTreeOwner.h"
|
||||
#include "nsCOMPtr.h"
|
||||
@ -461,10 +460,6 @@ class BrowserParent final : public PBrowserParent,
|
||||
|
||||
bool DeallocPColorPickerParent(PColorPickerParent* aColorPicker);
|
||||
|
||||
PVsyncParent* AllocPVsyncParent();
|
||||
|
||||
bool DeallocPVsyncParent(PVsyncParent* aActor);
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
PDocAccessibleParent* AllocPDocAccessibleParent(PDocAccessibleParent*,
|
||||
const uint64_t&,
|
||||
@ -877,8 +872,6 @@ class BrowserParent final : public PBrowserParent,
|
||||
void SendRealTouchMoveEvent(WidgetTouchEvent& aEvent, APZData& aAPZData,
|
||||
uint32_t aConsecutiveTouchMoveCount);
|
||||
|
||||
void UpdateVsyncParentVsyncSource();
|
||||
|
||||
public:
|
||||
// Unsets sTopLevelWebFocus regardless of its current value.
|
||||
static void UnsetTopLevelWebFocusAll();
|
||||
@ -964,8 +957,6 @@ class BrowserParent final : public PBrowserParent,
|
||||
|
||||
nsTArray<nsString> mVerifyDropLinks;
|
||||
|
||||
RefPtr<VsyncParent> mVsyncParent;
|
||||
|
||||
#ifdef DEBUG
|
||||
int32_t mActiveSupressDisplayportCount = 0;
|
||||
#endif
|
||||
|
@ -20,7 +20,6 @@ include protocol PRemoteLazyInputStream;
|
||||
include protocol PPaymentRequest;
|
||||
include protocol PWindowGlobal;
|
||||
include protocol PBrowserBridge;
|
||||
include protocol PVsync;
|
||||
|
||||
include DOMTypes;
|
||||
include NeckoChannelParams;
|
||||
@ -191,7 +190,6 @@ nested(upto inside_cpow) sync refcounted protocol PBrowser
|
||||
manages PPaymentRequest;
|
||||
manages PWindowGlobal;
|
||||
manages PBrowserBridge;
|
||||
manages PVsync;
|
||||
|
||||
both:
|
||||
async AsyncMessage(nsString aMessage, ClonedMessageData aData);
|
||||
@ -219,11 +217,6 @@ parent:
|
||||
|
||||
async PPaymentRequest();
|
||||
|
||||
/**
|
||||
* Create a new Vsync connection for our associated root widget
|
||||
*/
|
||||
async PVsync();
|
||||
|
||||
/**
|
||||
* Sends an NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW to be adopted by the
|
||||
* widget's shareable window on the chrome side. Only used on Windows.
|
||||
|
@ -71,8 +71,6 @@ EXPORTS.mozilla.dom += [
|
||||
"URLClassifierChild.h",
|
||||
"URLClassifierParent.h",
|
||||
"UserActivationIPCUtils.h",
|
||||
"VsyncChild.h",
|
||||
"VsyncParent.h",
|
||||
"WindowGlobalActor.h",
|
||||
"WindowGlobalChild.h",
|
||||
"WindowGlobalParent.h",
|
||||
@ -132,8 +130,6 @@ UNIFIED_SOURCES += [
|
||||
SOURCES += [
|
||||
"ContentChild.cpp",
|
||||
"ProcessHangMonitor.cpp",
|
||||
"VsyncChild.cpp",
|
||||
"VsyncParent.cpp",
|
||||
]
|
||||
|
||||
PREPROCESSED_IPDL_SOURCES += [
|
||||
@ -159,7 +155,6 @@ IPDL_SOURCES += [
|
||||
"PURLClassifier.ipdl",
|
||||
"PURLClassifierInfo.ipdlh",
|
||||
"PURLClassifierLocal.ipdl",
|
||||
"PVsync.ipdl",
|
||||
"PWindowGlobal.ipdl",
|
||||
"ServiceWorkerConfiguration.ipdlh",
|
||||
"WindowGlobalTypes.ipdlh",
|
||||
|
@ -46,11 +46,11 @@
|
||||
#include "mozilla/dom/ServiceWorkerContainerChild.h"
|
||||
#include "mozilla/dom/ServiceWorkerManagerChild.h"
|
||||
#include "mozilla/dom/BrowserChild.h"
|
||||
#include "mozilla/dom/VsyncChild.h"
|
||||
#include "mozilla/ipc/IPCStreamAlloc.h"
|
||||
#include "mozilla/ipc/PBackgroundTestChild.h"
|
||||
#include "mozilla/ipc/PChildToParentStreamChild.h"
|
||||
#include "mozilla/ipc/PParentToChildStreamChild.h"
|
||||
#include "mozilla/layout/VsyncChild.h"
|
||||
#include "mozilla/net/HttpBackgroundChannelChild.h"
|
||||
#include "mozilla/net/PUDPSocketChild.h"
|
||||
#include "mozilla/dom/network/UDPSocketChild.h"
|
||||
@ -408,8 +408,8 @@ bool BackgroundChildImpl::DeallocPFileDescriptorSetChild(
|
||||
return true;
|
||||
}
|
||||
|
||||
dom::PVsyncChild* BackgroundChildImpl::AllocPVsyncChild() {
|
||||
RefPtr<dom::VsyncChild> actor = new dom::VsyncChild();
|
||||
BackgroundChildImpl::PVsyncChild* BackgroundChildImpl::AllocPVsyncChild() {
|
||||
RefPtr<mozilla::layout::VsyncChild> actor = new mozilla::layout::VsyncChild();
|
||||
// There still has one ref-count after return, and it will be released in
|
||||
// DeallocPVsyncChild().
|
||||
return actor.forget().take();
|
||||
@ -419,8 +419,8 @@ bool BackgroundChildImpl::DeallocPVsyncChild(PVsyncChild* aActor) {
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
// This actor already has one ref-count. Please check AllocPVsyncChild().
|
||||
RefPtr<dom::VsyncChild> actor =
|
||||
dont_AddRef(static_cast<dom::VsyncChild*>(aActor));
|
||||
RefPtr<mozilla::layout::VsyncChild> actor =
|
||||
dont_AddRef(static_cast<mozilla::layout::VsyncChild*>(aActor));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -619,7 +619,7 @@ bool BackgroundChildImpl::DeallocPClientManagerChild(
|
||||
|
||||
#ifdef EARLY_BETA_OR_EARLIER
|
||||
void BackgroundChildImpl::OnChannelReceivedMessage(const Message& aMsg) {
|
||||
if (aMsg.type() == dom::PVsync::MessageType::Msg_Notify__ID) {
|
||||
if (aMsg.type() == layout::PVsync::MessageType::Msg_Notify__ID) {
|
||||
// Not really necessary to look at the message payload, it will be
|
||||
// <0.5ms away from TimeStamp::Now()
|
||||
SchedulerGroup::MarkVsyncReceived();
|
||||
|
@ -55,7 +55,6 @@
|
||||
#include "mozilla/dom/network/UDPSocketParent.h"
|
||||
#include "mozilla/dom/quota/ActorsParent.h"
|
||||
#include "mozilla/dom/simpledb/ActorsParent.h"
|
||||
#include "mozilla/dom/VsyncParent.h"
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
#include "mozilla/ipc/Endpoint.h"
|
||||
@ -65,6 +64,7 @@
|
||||
#include "mozilla/ipc/PBackgroundTestParent.h"
|
||||
#include "mozilla/ipc/PChildToParentStreamParent.h"
|
||||
#include "mozilla/ipc/PParentToChildStreamParent.h"
|
||||
#include "mozilla/layout/VsyncParent.h"
|
||||
#include "mozilla/media/MediaParent.h"
|
||||
#include "mozilla/net/BackgroundDataBridgeParent.h"
|
||||
#include "mozilla/net/HttpBackgroundChannelParent.h"
|
||||
@ -717,8 +717,8 @@ BackgroundParentImpl::PVsyncParent* BackgroundParentImpl::AllocPVsyncParent() {
|
||||
AssertIsInMainOrSocketProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
RefPtr<mozilla::dom::VsyncParent> actor = new mozilla::dom::VsyncParent();
|
||||
actor->UpdateVsyncSource(nullptr);
|
||||
RefPtr<mozilla::layout::VsyncParent> actor =
|
||||
mozilla::layout::VsyncParent::Create();
|
||||
// There still has one ref-count after return, and it will be released in
|
||||
// DeallocPVsyncParent().
|
||||
return actor.forget().take();
|
||||
@ -730,8 +730,8 @@ bool BackgroundParentImpl::DeallocPVsyncParent(PVsyncParent* aActor) {
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
// This actor already has one ref-count. Please check AllocPVsyncParent().
|
||||
RefPtr<mozilla::dom::VsyncParent> actor =
|
||||
dont_AddRef(static_cast<mozilla::dom::VsyncParent*>(aActor));
|
||||
RefPtr<mozilla::layout::VsyncParent> actor =
|
||||
dont_AddRef(static_cast<mozilla::layout::VsyncParent*>(aActor));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,11 @@
|
||||
#include "mozilla/ipc/PBackgroundParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace layout {
|
||||
class VsyncParent;
|
||||
} // namespace layout
|
||||
|
||||
namespace ipc {
|
||||
|
||||
// Instances of this class should never be created directly. This class is meant
|
||||
|
@ -692,6 +692,9 @@ nsresult nsPresContext::Init(nsDeviceContext* aDeviceContext) {
|
||||
|
||||
if (!mRefreshDriver) {
|
||||
mRefreshDriver = new nsRefreshDriver(this);
|
||||
if (XRE_IsContentProcess()) {
|
||||
mRefreshDriver->InitializeTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,12 +59,10 @@
|
||||
#include "nsViewManager.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#include "mozilla/dom/BrowserChild.h"
|
||||
#include "mozilla/dom/CallbackDebuggerNotification.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/dom/VsyncChild.h"
|
||||
#include "mozilla/dom/WindowBinding.h"
|
||||
#include "mozilla/RestyleManager.h"
|
||||
#include "Layers.h"
|
||||
@ -77,6 +75,7 @@
|
||||
|
||||
#include "BackgroundChild.h"
|
||||
#include "mozilla/ipc/PBackgroundChild.h"
|
||||
#include "mozilla/layout/VsyncChild.h"
|
||||
#include "VsyncSource.h"
|
||||
#include "mozilla/VsyncDispatcher.h"
|
||||
#include "mozilla/Unused.h"
|
||||
@ -247,6 +246,26 @@ class RefreshDriverTimer {
|
||||
|
||||
TimeStamp MostRecentRefresh() const { return mLastFireTime; }
|
||||
|
||||
void SwapRefreshDrivers(RefreshDriverTimer* aNewTimer) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
for (nsRefreshDriver* driver : mContentRefreshDrivers) {
|
||||
aNewTimer->AddRefreshDriver(driver);
|
||||
driver->mActiveTimer = aNewTimer;
|
||||
}
|
||||
mContentRefreshDrivers.Clear();
|
||||
|
||||
for (nsRefreshDriver* driver : mRootRefreshDrivers) {
|
||||
aNewTimer->AddRefreshDriver(driver);
|
||||
driver->mActiveTimer = aNewTimer;
|
||||
}
|
||||
mRootRefreshDrivers.Clear();
|
||||
|
||||
aNewTimer->mLastFireTime = mLastFireTime;
|
||||
|
||||
StopTimer();
|
||||
}
|
||||
|
||||
virtual TimeDuration GetTimerRate() = 0;
|
||||
|
||||
TimeStamp GetIdleDeadlineHint(TimeStamp aDefault) {
|
||||
@ -427,45 +446,56 @@ class SimpleTimerBasedRefreshDriverTimer : public RefreshDriverTimer {
|
||||
*/
|
||||
class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||
public:
|
||||
VsyncRefreshDriverTimer()
|
||||
: mVsyncChild(nullptr), mVsyncRate(TimeDuration::Forever()) {
|
||||
VsyncRefreshDriverTimer() : mVsyncChild(nullptr) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mVsyncSource = gfxPlatform::GetPlatform()->GetHardwareVsync();
|
||||
mVsyncObserver = new RefreshDriverVsyncObserver(this);
|
||||
RefPtr<mozilla::gfx::VsyncSource> vsyncSource =
|
||||
gfxPlatform::GetPlatform()->GetHardwareVsync();
|
||||
MOZ_ALWAYS_TRUE(mVsyncDispatcher =
|
||||
mVsyncSource->GetRefreshTimerVsyncDispatcher());
|
||||
vsyncSource->GetRefreshTimerVsyncDispatcher());
|
||||
mVsyncDispatcher->AddChildRefreshTimer(mVsyncObserver);
|
||||
mVsyncRate = vsyncSource->GetGlobalDisplay().GetVsyncRate();
|
||||
}
|
||||
|
||||
explicit VsyncRefreshDriverTimer(VsyncChild* aVsyncChild)
|
||||
: mVsyncChild(aVsyncChild) {
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mVsyncChild);
|
||||
mVsyncObserver = new RefreshDriverVsyncObserver(this);
|
||||
mVsyncChild->SetVsyncObserver(mVsyncObserver);
|
||||
mVsyncRate = mVsyncChild->GetVsyncRate();
|
||||
}
|
||||
|
||||
// Constructor for when we have a local vsync source. As it is local, we do
|
||||
// not have to worry about it being re-inited by gfxPlatform on frame rate
|
||||
// change on the global source.
|
||||
explicit VsyncRefreshDriverTimer(const RefPtr<gfx::VsyncSource>& aVsyncSource)
|
||||
: mVsyncSource(aVsyncSource),
|
||||
mVsyncChild(nullptr),
|
||||
mVsyncRate(TimeDuration::Forever()) {
|
||||
: mVsyncChild(nullptr) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mVsyncSource = aVsyncSource;
|
||||
mVsyncObserver = new RefreshDriverVsyncObserver(this);
|
||||
MOZ_ALWAYS_TRUE(mVsyncDispatcher =
|
||||
aVsyncSource->GetRefreshTimerVsyncDispatcher());
|
||||
}
|
||||
|
||||
explicit VsyncRefreshDriverTimer(const RefPtr<VsyncChild>& aVsyncChild)
|
||||
: mVsyncSource(nullptr),
|
||||
mVsyncDispatcher(nullptr),
|
||||
mVsyncChild(aVsyncChild),
|
||||
mVsyncRate(TimeDuration::Forever()) {
|
||||
MOZ_ASSERT(XRE_IsContentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mVsyncObserver = new RefreshDriverVsyncObserver(this);
|
||||
mVsyncDispatcher->AddChildRefreshTimer(mVsyncObserver);
|
||||
mVsyncRate = aVsyncSource->GetGlobalDisplay().GetVsyncRate();
|
||||
}
|
||||
|
||||
TimeDuration GetTimerRate() override {
|
||||
if (mVsyncSource) {
|
||||
mVsyncRate = mVsyncSource->GetGlobalDisplay().GetVsyncRate();
|
||||
} else if (mVsyncChild) {
|
||||
mVsyncRate = mVsyncChild->GetVsyncRate();
|
||||
if (mVsyncRate != TimeDuration::Forever()) {
|
||||
return mVsyncRate;
|
||||
}
|
||||
|
||||
if (mVsyncChild) {
|
||||
// VsyncChild::VsyncRate() is a simple getter for the cached
|
||||
// hardware vsync rate. We depend on that
|
||||
// VsyncChild::GetVsyncRate() being called in the constructor
|
||||
// will result in a response with the actual vsync rate sooner
|
||||
// or later. Until that happens VsyncChild::VsyncRate() returns
|
||||
// TimeDuration::Forever() and we have to guess below.
|
||||
mVsyncRate = mVsyncChild->VsyncRate();
|
||||
}
|
||||
|
||||
// If hardware queries fail / are unsupported, we have to just guess.
|
||||
@ -742,11 +772,16 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||
}; // RefreshDriverVsyncObserver
|
||||
|
||||
~VsyncRefreshDriverTimer() override {
|
||||
if (mVsyncDispatcher) {
|
||||
if (XRE_IsParentProcess()) {
|
||||
mVsyncDispatcher->RemoveChildRefreshTimer(mVsyncObserver);
|
||||
mVsyncDispatcher = nullptr;
|
||||
} else if (mVsyncChild) {
|
||||
mVsyncChild->RemoveChildRefreshTimer(mVsyncObserver);
|
||||
} else {
|
||||
// Since the PVsyncChild actors live through the life of the process, just
|
||||
// send the unobserveVsync message to disable vsync event. We don't need
|
||||
// to handle the cleanup stuff of this actor. PVsyncChild::ActorDestroy()
|
||||
// will be called and clean up this actor.
|
||||
Unused << mVsyncChild->SendUnobserve();
|
||||
mVsyncChild->SetVsyncObserver(nullptr);
|
||||
mVsyncChild = nullptr;
|
||||
}
|
||||
|
||||
@ -762,10 +797,10 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||
|
||||
mLastFireTime = TimeStamp::Now();
|
||||
|
||||
if (mVsyncDispatcher) {
|
||||
if (XRE_IsParentProcess()) {
|
||||
mVsyncDispatcher->AddChildRefreshTimer(mVsyncObserver);
|
||||
} else if (mVsyncChild) {
|
||||
mVsyncChild->AddChildRefreshTimer(mVsyncObserver);
|
||||
} else {
|
||||
Unused << mVsyncChild->SendObserve();
|
||||
mVsyncObserver->OnTimerStart();
|
||||
}
|
||||
|
||||
@ -776,10 +811,10 @@ class VsyncRefreshDriverTimer : public RefreshDriverTimer {
|
||||
// Protect updates to `sActiveVsyncTimers`.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mVsyncDispatcher) {
|
||||
if (XRE_IsParentProcess()) {
|
||||
mVsyncDispatcher->RemoveChildRefreshTimer(mVsyncObserver);
|
||||
} else if (mVsyncChild) {
|
||||
mVsyncChild->RemoveChildRefreshTimer(mVsyncObserver);
|
||||
} else {
|
||||
Unused << mVsyncChild->SendUnobserve();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(sActiveVsyncTimers > 0);
|
||||
@ -971,12 +1006,34 @@ class InactiveRefreshDriverTimer final
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
static nsTArray<RefreshDriverTimer*>* sRegularRateTimers;
|
||||
static StaticRefPtr<RefreshDriverTimer> sRegularRateTimer;
|
||||
static StaticRefPtr<InactiveRefreshDriverTimer> sThrottledRateTimer;
|
||||
|
||||
static void CreateContentVsyncRefreshTimer(void*) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
|
||||
// Create the PVsync actor child for vsync-base refresh timer.
|
||||
// PBackgroundChild is created synchronously. We will still use software
|
||||
// timer before PVsync ready, and change to use hw timer when the connection
|
||||
// is done. Please check nsRefreshDriver::PVsyncActorCreated().
|
||||
|
||||
PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread();
|
||||
if (NS_WARN_IF(!actorChild)) {
|
||||
return;
|
||||
}
|
||||
|
||||
layout::PVsyncChild* actor = actorChild->SendPVsyncConstructor();
|
||||
if (NS_WARN_IF(!actor)) {
|
||||
return;
|
||||
}
|
||||
|
||||
layout::VsyncChild* child = static_cast<layout::VsyncChild*>(actor);
|
||||
nsRefreshDriver::PVsyncActorCreated(child);
|
||||
}
|
||||
|
||||
void nsRefreshDriver::CreateVsyncRefreshTimer() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mOwnTimer);
|
||||
|
||||
PodArrayZero(sJankLevels);
|
||||
|
||||
@ -985,25 +1042,32 @@ void nsRefreshDriver::CreateVsyncRefreshTimer() {
|
||||
}
|
||||
|
||||
// If available, we fetch the widget-specific vsync source.
|
||||
//
|
||||
// NOTE(heycam): If we are initializing an nsRefreshDriver under
|
||||
// nsPresContext::Init, then this GetRootWidget() call will fail, as the
|
||||
// pres context does not yet have a pres shell. For now, null check the
|
||||
// pres shell to avoid a console warning.
|
||||
nsPresContext* pc = GetPresContext();
|
||||
nsIWidget* widget = pc->GetPresShell() ? pc->GetRootWidget() : nullptr;
|
||||
if (widget) {
|
||||
if (RefPtr<gfx::VsyncSource> localVsyncSource = widget->GetVsyncSource()) {
|
||||
RefPtr<gfx::VsyncSource> localVsyncSource = widget->GetVsyncSource();
|
||||
if (localVsyncSource) {
|
||||
mOwnTimer = new VsyncRefreshDriverTimer(localVsyncSource);
|
||||
} else if (BrowserChild* browserChild = widget->GetOwningBrowserChild()) {
|
||||
if (RefPtr<VsyncChild> localVsyncSource = browserChild->GetVsyncChild()) {
|
||||
mOwnTimer = new VsyncRefreshDriverTimer(localVsyncSource);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mOwnTimer) {
|
||||
mOwnTimer = new StartupRefreshDriverTimer(GetRegularTimerInterval());
|
||||
if (XRE_IsParentProcess()) {
|
||||
// Make sure all vsync systems are ready.
|
||||
gfxPlatform::GetPlatform();
|
||||
// In parent process, we don't need to use ipc. We can create the
|
||||
// VsyncRefreshDriverTimer directly.
|
||||
sRegularRateTimer = new VsyncRefreshDriverTimer();
|
||||
return;
|
||||
}
|
||||
if (!sRegularRateTimers) {
|
||||
sRegularRateTimers = new nsTArray<RefreshDriverTimer*>();
|
||||
}
|
||||
sRegularRateTimers->AppendElement(mOwnTimer.get());
|
||||
|
||||
// If this process is not created by NUWA, just create the vsync timer here.
|
||||
CreateContentVsyncRefreshTimer(nullptr);
|
||||
}
|
||||
|
||||
static uint32_t GetFirstFrameDelay(imgIRequest* req) {
|
||||
@ -1021,10 +1085,8 @@ static uint32_t GetFirstFrameDelay(imgIRequest* req) {
|
||||
|
||||
/* static */
|
||||
void nsRefreshDriver::Shutdown() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// clean up our timers
|
||||
delete sRegularRateTimers;
|
||||
sRegularRateTimers = nullptr;
|
||||
sRegularRateTimer = nullptr;
|
||||
sThrottledRateTimer = nullptr;
|
||||
}
|
||||
|
||||
@ -1080,10 +1142,26 @@ RefreshDriverTimer* nsRefreshDriver::ChooseTimer() {
|
||||
return sThrottledRateTimer;
|
||||
}
|
||||
|
||||
if (!mOwnTimer) {
|
||||
if (!sRegularRateTimer && !mOwnTimer) {
|
||||
double rate = GetRegularTimerInterval();
|
||||
|
||||
// Try to use vsync-base refresh timer first for sRegularRateTimer.
|
||||
CreateVsyncRefreshTimer();
|
||||
|
||||
if (mOwnTimer) {
|
||||
return mOwnTimer.get();
|
||||
}
|
||||
|
||||
if (!sRegularRateTimer) {
|
||||
sRegularRateTimer = new StartupRefreshDriverTimer(rate);
|
||||
}
|
||||
}
|
||||
return mOwnTimer.get();
|
||||
|
||||
if (mOwnTimer) {
|
||||
return mOwnTimer.get();
|
||||
}
|
||||
|
||||
return sRegularRateTimer;
|
||||
}
|
||||
|
||||
nsRefreshDriver::nsRefreshDriver(nsPresContext* aPresContext)
|
||||
@ -1135,9 +1213,6 @@ nsRefreshDriver::~nsRefreshDriver() {
|
||||
mRootRefresh->RemoveRefreshObserver(this, FlushType::Style);
|
||||
mRootRefresh = nullptr;
|
||||
}
|
||||
if (mOwnTimer && sRegularRateTimers) {
|
||||
sRegularRateTimers->RemoveElement(mOwnTimer.get());
|
||||
}
|
||||
}
|
||||
|
||||
// Method for testing. See nsIDOMWindowUtils.advanceTimeAndRefresh
|
||||
@ -2600,6 +2675,21 @@ void nsRefreshDriver::SetThrottled(bool aThrottled) {
|
||||
|
||||
nsPresContext* nsRefreshDriver::GetPresContext() const { return mPresContext; }
|
||||
|
||||
/*static*/
|
||||
void nsRefreshDriver::PVsyncActorCreated(VsyncChild* aVsyncChild) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
RefPtr<RefreshDriverTimer> vsyncRefreshDriverTimer =
|
||||
new VsyncRefreshDriverTimer(aVsyncChild);
|
||||
|
||||
// If we are using software timer, swap current timer to
|
||||
// VsyncRefreshDriverTimer.
|
||||
if (sRegularRateTimer) {
|
||||
sRegularRateTimer->SwapRefreshDrivers(vsyncRefreshDriverTimer);
|
||||
}
|
||||
sRegularRateTimer = std::move(vsyncRefreshDriverTimer);
|
||||
}
|
||||
|
||||
void nsRefreshDriver::DoRefresh() {
|
||||
// Don't do a refresh unless we're in a state where we should be refreshing.
|
||||
if (!IsFrozen() && mPresContext && mActiveTimer) {
|
||||
@ -2676,34 +2766,27 @@ TimeStamp nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!aDefault.IsNull());
|
||||
|
||||
if (!sRegularRateTimers || sRegularRateTimers->IsEmpty()) {
|
||||
if (!sRegularRateTimer) {
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
// For computing idleness of refresh drivers we only care about
|
||||
// sRegularRateTimers, since we consider refresh drivers attached to
|
||||
// sRegularRateTimer, since we consider refresh drivers attached to
|
||||
// sThrottledRateTimer to be inactive. This implies that tasks
|
||||
// resulting from a tick on the sRegularRateTimer counts as being
|
||||
// busy but tasks resulting from a tick on sThrottledRateTimer
|
||||
// counts as being idle.
|
||||
return sRegularRateTimers->ElementAt(0)->GetIdleDeadlineHint(aDefault);
|
||||
return sRegularRateTimer->GetIdleDeadlineHint(aDefault);
|
||||
}
|
||||
|
||||
/* static */
|
||||
Maybe<TimeStamp> nsRefreshDriver::GetNextTickHint() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!sRegularRateTimers) {
|
||||
if (!sRegularRateTimer) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
for (RefreshDriverTimer* timer : *sRegularRateTimers) {
|
||||
Maybe<TimeStamp> tickHint = timer->GetNextTickHint();
|
||||
if (tickHint.isSome()) {
|
||||
return tickHint;
|
||||
}
|
||||
}
|
||||
return Nothing();
|
||||
return sRegularRateTimer->GetNextTickHint();
|
||||
}
|
||||
|
||||
void nsRefreshDriver::Disconnect() {
|
||||
|
@ -43,6 +43,10 @@ class PresShell;
|
||||
class RefreshDriverTimer;
|
||||
class Runnable;
|
||||
|
||||
namespace layout {
|
||||
class VsyncChild;
|
||||
} // namespace layout
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
||||
@ -294,6 +298,14 @@ class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
||||
*/
|
||||
nsPresContext* GetPresContext() const;
|
||||
|
||||
/**
|
||||
* PBackgroundChild actor is created asynchronously in content process.
|
||||
* We can't create vsync-based timers during PBackground startup. This
|
||||
* function will be called when PBackgroundChild actor is created. Then we can
|
||||
* do the pending vsync-based timer creation.
|
||||
*/
|
||||
static void PVsyncActorCreated(mozilla::layout::VsyncChild* aVsyncChild);
|
||||
|
||||
void CreateVsyncRefreshTimer();
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -23,6 +23,9 @@ class AnimationEventDispatcher;
|
||||
class PendingFullscreenEvent;
|
||||
class PresShell;
|
||||
class RefreshDriverTimer;
|
||||
namespace layout {
|
||||
class VsyncChild;
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
|
@ -4,23 +4,22 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PBackground;
|
||||
include protocol PBrowser;
|
||||
include "mozilla/layers/LayersMessageUtils.h";
|
||||
|
||||
using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
|
||||
using mozilla::VsyncEvent from "mozilla/VsyncDispatcher.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace layout {
|
||||
|
||||
/*
|
||||
* The PVsync is a sub-protocol in PBackground or PBrowser and it is used to
|
||||
* notify the vsync event from chrome to content process. It also provides the
|
||||
* The PVsync is a sub-protocol in PBackground and it is used to notify
|
||||
* the vsync event from chrome to content process. It also provides the
|
||||
* interfaces for content to observe/unobserve vsync event notifications.
|
||||
*/
|
||||
async protocol PVsync
|
||||
{
|
||||
manager PBackground or PBrowser;
|
||||
manager PBackground;
|
||||
|
||||
child:
|
||||
// Send vsync event from chrome to content process.
|
||||
@ -36,9 +35,10 @@ parent:
|
||||
async RequestVsyncRate();
|
||||
|
||||
// This message is never sent. Each PVsync actor will stay alive as long as
|
||||
// its PBackground or PBrowser manager.
|
||||
// its PBackground manager.
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace layout
|
||||
} // namespace mozilla
|
||||
|
@ -10,18 +10,17 @@
|
||||
#include "mozilla/VsyncDispatcher.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
namespace mozilla::layout {
|
||||
|
||||
VsyncChild::VsyncChild()
|
||||
: mIsShutdown(false),
|
||||
mVsyncRate(TimeDuration::Forever()),
|
||||
lastVsyncRateTime(TimeStamp()) {
|
||||
: mObservingVsync(false),
|
||||
mIsShutdown(false),
|
||||
mVsyncRate(TimeDuration::Forever()) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
VsyncChild::~VsyncChild() { MOZ_ASSERT(NS_IsMainThread()); }
|
||||
|
||||
/* do not delete yet so the file history is preserved
|
||||
bool VsyncChild::SendObserve() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mObservingVsync && !mIsShutdown) {
|
||||
@ -39,42 +38,12 @@ bool VsyncChild::SendUnobserve() {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
void VsyncChild::AddChildRefreshTimer(VsyncObserver* aVsyncObserver) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mObservers.Contains(aVsyncObserver));
|
||||
|
||||
if (mIsShutdown) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mObservers.IsEmpty()) {
|
||||
Unused << PVsyncChild::SendObserve();
|
||||
}
|
||||
mObservers.AppendElement(std::move(aVsyncObserver));
|
||||
}
|
||||
|
||||
void VsyncChild::RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mIsShutdown) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mObservers.RemoveElement(aVsyncObserver) && mObservers.IsEmpty()) {
|
||||
Unused << PVsyncChild::SendUnobserve();
|
||||
}
|
||||
}
|
||||
|
||||
void VsyncChild::ActorDestroy(ActorDestroyReason aActorDestroyReason) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mIsShutdown);
|
||||
mIsShutdown = true;
|
||||
|
||||
if (!mObservers.IsEmpty()) {
|
||||
Unused << PVsyncChild::SendUnobserve();
|
||||
}
|
||||
mObservers.Clear();
|
||||
mObserver = nullptr;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult VsyncChild::RecvNotify(const VsyncEvent& aVsync) {
|
||||
@ -82,26 +51,30 @@ mozilla::ipc::IPCResult VsyncChild::RecvNotify(const VsyncEvent& aVsync) {
|
||||
MOZ_ASSERT(!mIsShutdown);
|
||||
|
||||
SchedulerGroup::MarkVsyncRan();
|
||||
|
||||
for (VsyncObserver* observer : mObservers.ForwardRange()) {
|
||||
observer->NotifyVsync(aVsync);
|
||||
if (mObservingVsync && mObserver) {
|
||||
mObserver->NotifyVsync(aVsync);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void VsyncChild::SetVsyncObserver(VsyncObserver* aVsyncObserver) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mObserver = aVsyncObserver;
|
||||
}
|
||||
|
||||
TimeDuration VsyncChild::GetVsyncRate() {
|
||||
// Throttle vsync rate requests to avoid unnecessary IPC
|
||||
if (lastVsyncRateTime.IsNull() ||
|
||||
(TimeStamp::Now() - lastVsyncRateTime).ToMilliseconds() > 250) {
|
||||
if (mVsyncRate == TimeDuration::Forever()) {
|
||||
PVsyncChild::SendRequestVsyncRate();
|
||||
lastVsyncRateTime = TimeStamp::Now();
|
||||
}
|
||||
|
||||
return mVsyncRate;
|
||||
}
|
||||
|
||||
TimeDuration VsyncChild::VsyncRate() { return mVsyncRate; }
|
||||
|
||||
mozilla::ipc::IPCResult VsyncChild::RecvVsyncRate(const float& aVsyncRate) {
|
||||
mVsyncRate = TimeDuration::FromMilliseconds(aVsyncRate);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
} // namespace mozilla::layout
|
@ -4,19 +4,22 @@
|
||||
* 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_VsyncChild_h
|
||||
#define mozilla_dom_ipc_VsyncChild_h
|
||||
#ifndef mozilla_layout_ipc_VsyncChild_h
|
||||
#define mozilla_layout_ipc_VsyncChild_h
|
||||
|
||||
#include "mozilla/dom/PVsyncChild.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/layout/PVsyncChild.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class VsyncObserver;
|
||||
|
||||
namespace dom {
|
||||
namespace ipc {
|
||||
class BackgroundChildImpl;
|
||||
} // namespace ipc
|
||||
|
||||
namespace layout {
|
||||
|
||||
// The PVsyncChild actor receives a vsync event from the main process and
|
||||
// delivers it to the child process. Currently this is restricted to the main
|
||||
@ -25,30 +28,44 @@ namespace dom {
|
||||
class VsyncChild final : public PVsyncChild {
|
||||
NS_INLINE_DECL_REFCOUNTING(VsyncChild)
|
||||
|
||||
friend class mozilla::ipc::BackgroundChildImpl;
|
||||
friend class PVsyncChild;
|
||||
|
||||
public:
|
||||
VsyncChild();
|
||||
|
||||
void AddChildRefreshTimer(VsyncObserver* aVsyncObserver);
|
||||
void RemoveChildRefreshTimer(VsyncObserver* aVsyncObserver);
|
||||
// Hide the SendObserve/SendUnobserve in PVsyncChild. We add an flag
|
||||
// mObservingVsync to handle the race problem of unobserving vsync event.
|
||||
bool SendObserve();
|
||||
bool SendUnobserve();
|
||||
|
||||
// Bind a VsyncObserver into VsyncChild after ipc channel connected.
|
||||
void SetVsyncObserver(VsyncObserver* aVsyncObserver);
|
||||
// GetVsyncRate is a getter for mVsyncRate which sends a requests to
|
||||
// VsyncParent to retreive the hardware vsync rate if mVsyncRate
|
||||
// hasn't already been set.
|
||||
TimeDuration GetVsyncRate();
|
||||
// VsyncRate is a getter for mVsyncRate which always returns
|
||||
// mVsyncRate directly, potentially returning
|
||||
// TimeDuration::Forever() if mVsyncRate hasn't been set by calling
|
||||
// GetVsyncRate.
|
||||
TimeDuration VsyncRate();
|
||||
|
||||
private:
|
||||
VsyncChild();
|
||||
virtual ~VsyncChild();
|
||||
|
||||
mozilla::ipc::IPCResult RecvNotify(const VsyncEvent& aVsync);
|
||||
mozilla::ipc::IPCResult RecvVsyncRate(const float& aVsyncRate);
|
||||
virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
|
||||
|
||||
bool mObservingVsync;
|
||||
bool mIsShutdown;
|
||||
|
||||
// The content side vsync observer.
|
||||
RefPtr<VsyncObserver> mObserver;
|
||||
TimeDuration mVsyncRate;
|
||||
TimeStamp lastVsyncRateTime;
|
||||
nsTObserverArray<VsyncObserver*> mObservers;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace layout
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ipc_VsyncChild_h
|
||||
#endif // mozilla_layout_ipc_VsyncChild_h
|
@ -10,49 +10,51 @@
|
||||
#include "BackgroundParentImpl.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "VsyncSource.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
namespace mozilla {
|
||||
|
||||
using namespace ipc;
|
||||
|
||||
namespace layout {
|
||||
|
||||
/*static*/
|
||||
already_AddRefed<VsyncParent> VsyncParent::Create() {
|
||||
AssertIsOnBackgroundThread();
|
||||
RefPtr<gfx::VsyncSource> vsyncSource =
|
||||
gfxPlatform::GetPlatform()->GetHardwareVsync();
|
||||
RefPtr<VsyncParent> vsyncParent = new VsyncParent();
|
||||
vsyncParent->mVsyncDispatcher = vsyncSource->GetRefreshTimerVsyncDispatcher();
|
||||
return vsyncParent.forget();
|
||||
}
|
||||
|
||||
VsyncParent::VsyncParent()
|
||||
: mObservingVsync(false),
|
||||
mDestroyed(false),
|
||||
mInitialThread(NS_GetCurrentThread()) {}
|
||||
mBackgroundThread(NS_GetCurrentThread()) {
|
||||
MOZ_ASSERT(mBackgroundThread);
|
||||
AssertIsOnBackgroundThread();
|
||||
}
|
||||
|
||||
void VsyncParent::UpdateVsyncSource(
|
||||
const RefPtr<gfx::VsyncSource>& aVsyncSource) {
|
||||
mVsyncSource = aVsyncSource;
|
||||
if (!mVsyncSource) {
|
||||
mVsyncSource = gfxPlatform::GetPlatform()->GetHardwareVsync();
|
||||
}
|
||||
|
||||
if (mObservingVsync) {
|
||||
mVsyncDispatcher->RemoveChildRefreshTimer(this);
|
||||
}
|
||||
mVsyncDispatcher = mVsyncSource->GetRefreshTimerVsyncDispatcher();
|
||||
if (mObservingVsync) {
|
||||
mVsyncDispatcher->AddChildRefreshTimer(this);
|
||||
}
|
||||
VsyncParent::~VsyncParent() {
|
||||
// Since we use NS_INLINE_DECL_THREADSAFE_REFCOUNTING, we can't make sure
|
||||
// VsyncParent is always released on the background thread.
|
||||
}
|
||||
|
||||
bool VsyncParent::NotifyVsync(const VsyncEvent& aVsync) {
|
||||
if (IsOnInitialThread()) {
|
||||
DispatchVsyncEvent(aVsync);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called on hardware vsync thread. We should post to current ipc thread.
|
||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||
nsCOMPtr<nsIRunnable> vsyncEvent = NewRunnableMethod<VsyncEvent>(
|
||||
"dom::VsyncParent::DispatchVsyncEvent", this,
|
||||
"layout::VsyncParent::DispatchVsyncEvent", this,
|
||||
&VsyncParent::DispatchVsyncEvent, aVsync);
|
||||
MOZ_ALWAYS_SUCCEEDS(mInitialThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL));
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL));
|
||||
return true;
|
||||
}
|
||||
|
||||
void VsyncParent::DispatchVsyncEvent(const VsyncEvent& aVsync) {
|
||||
AssertIsOnInitialThread();
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
// If we call NotifyVsync() when we handle ActorDestroy() message, we might
|
||||
// still call DispatchVsyncEvent().
|
||||
@ -65,14 +67,17 @@ void VsyncParent::DispatchVsyncEvent(const VsyncEvent& aVsync) {
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult VsyncParent::RecvRequestVsyncRate() {
|
||||
AssertIsOnInitialThread();
|
||||
TimeDuration vsyncRate = mVsyncSource->GetGlobalDisplay().GetVsyncRate();
|
||||
AssertIsOnBackgroundThread();
|
||||
TimeDuration vsyncRate = gfxPlatform::GetPlatform()
|
||||
->GetHardwareVsync()
|
||||
->GetGlobalDisplay()
|
||||
.GetVsyncRate();
|
||||
Unused << SendVsyncRate(vsyncRate.ToMilliseconds());
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult VsyncParent::RecvObserve() {
|
||||
AssertIsOnInitialThread();
|
||||
AssertIsOnBackgroundThread();
|
||||
if (!mObservingVsync) {
|
||||
mVsyncDispatcher->AddChildRefreshTimer(this);
|
||||
mObservingVsync = true;
|
||||
@ -82,7 +87,7 @@ mozilla::ipc::IPCResult VsyncParent::RecvObserve() {
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult VsyncParent::RecvUnobserve() {
|
||||
AssertIsOnInitialThread();
|
||||
AssertIsOnBackgroundThread();
|
||||
if (mObservingVsync) {
|
||||
mVsyncDispatcher->RemoveChildRefreshTimer(this);
|
||||
mObservingVsync = false;
|
||||
@ -91,9 +96,9 @@ mozilla::ipc::IPCResult VsyncParent::RecvUnobserve() {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
void VsyncParent::ActorDestroy(ActorDestroyReason aActorDestroyReason) {
|
||||
void VsyncParent::ActorDestroy(ActorDestroyReason aReason) {
|
||||
MOZ_ASSERT(!mDestroyed);
|
||||
AssertIsOnInitialThread();
|
||||
AssertIsOnBackgroundThread();
|
||||
if (mObservingVsync) {
|
||||
mVsyncDispatcher->RemoveChildRefreshTimer(this);
|
||||
}
|
||||
@ -101,10 +106,5 @@ void VsyncParent::ActorDestroy(ActorDestroyReason aActorDestroyReason) {
|
||||
mDestroyed = true;
|
||||
}
|
||||
|
||||
bool VsyncParent::IsOnInitialThread() {
|
||||
return NS_GetCurrentThread() == mInitialThread;
|
||||
}
|
||||
|
||||
void VsyncParent::AssertIsOnInitialThread() { MOZ_ASSERT(IsOnInitialThread()); }
|
||||
|
||||
} // namespace mozilla::dom
|
||||
} // namespace layout
|
||||
} // namespace mozilla
|
@ -4,31 +4,36 @@
|
||||
* 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_VsyncParent_h
|
||||
#define mozilla_dom_ipc_VsyncParent_h
|
||||
#ifndef mozilla_layout_ipc_VsyncParent_h
|
||||
#define mozilla_layout_ipc_VsyncParent_h
|
||||
|
||||
#include "mozilla/dom/PVsyncParent.h"
|
||||
#include "mozilla/layout/PVsyncParent.h"
|
||||
#include "mozilla/VsyncDispatcher.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "VsyncSource.h"
|
||||
|
||||
class nsIThread;
|
||||
|
||||
namespace mozilla::dom {
|
||||
namespace mozilla {
|
||||
|
||||
namespace ipc {
|
||||
class BackgroundParentImpl;
|
||||
} // namespace ipc
|
||||
|
||||
namespace layout {
|
||||
|
||||
// Use PBackground thread in the main process to send vsync notifications to
|
||||
// content process. This actor will be released when its parent protocol calls
|
||||
// DeallocPVsyncParent().
|
||||
class VsyncParent final : public PVsyncParent, public VsyncObserver {
|
||||
friend class mozilla::ipc::BackgroundParentImpl;
|
||||
friend class PVsyncParent;
|
||||
|
||||
public:
|
||||
VsyncParent();
|
||||
void UpdateVsyncSource(const RefPtr<gfx::VsyncSource>& aVsyncSource);
|
||||
|
||||
private:
|
||||
virtual ~VsyncParent() = default;
|
||||
static already_AddRefed<VsyncParent> Create();
|
||||
|
||||
VsyncParent();
|
||||
virtual ~VsyncParent();
|
||||
|
||||
virtual bool NotifyVsync(const VsyncEvent& aVsync) override;
|
||||
mozilla::ipc::IPCResult RecvRequestVsyncRate();
|
||||
@ -39,16 +44,13 @@ class VsyncParent final : public PVsyncParent, public VsyncObserver {
|
||||
|
||||
void DispatchVsyncEvent(const VsyncEvent& aVsync);
|
||||
|
||||
bool IsOnInitialThread();
|
||||
void AssertIsOnInitialThread();
|
||||
|
||||
bool mObservingVsync;
|
||||
bool mDestroyed;
|
||||
nsCOMPtr<nsIThread> mInitialThread;
|
||||
RefPtr<gfx::VsyncSource> mVsyncSource;
|
||||
nsCOMPtr<nsIThread> mBackgroundThread;
|
||||
RefPtr<RefreshTimerVsyncDispatcher> mVsyncDispatcher;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
} // namespace layout
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ipc_VsyncParent_h
|
||||
#endif // mozilla_layout_ipc_VsyncParent_h
|
@ -9,12 +9,23 @@ with Files("**"):
|
||||
|
||||
EXPORTS.mozilla.layout += [
|
||||
"RemoteLayerTreeOwner.h",
|
||||
"VsyncChild.h",
|
||||
"VsyncParent.h",
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
"RemoteLayerTreeOwner.cpp",
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
"VsyncChild.cpp",
|
||||
"VsyncParent.cpp",
|
||||
]
|
||||
|
||||
IPDL_SOURCES = [
|
||||
"PVsync.ipdl",
|
||||
]
|
||||
|
||||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
FINAL_LIBRARY = "xul"
|
||||
|
Loading…
Reference in New Issue
Block a user