Bug 1333122 - Use the CompositorOptions to determine the appropriate LayerManager to create for content-process tabs. r=dvander
MozReview-Commit-ID: LRcHf5oCVlA
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -420,16 +420,24 @@ TabChild::TabChild(nsIContentChild* aMan
}
}
for (uint32_t idx = 0; idx < NUMBER_OF_AUDIO_CHANNELS; idx++) {
mAudioChannelsActive.AppendElement(false);
}
}
+const CompositorOptions&
+TabChild::GetCompositorOptions() const
+{
+ // If you're calling this before mCompositorOptions is set, well.. don't.
+ MOZ_ASSERT(mCompositorOptions);
+ return mCompositorOptions.ref();
+}
+
bool
TabChild::AsyncPanZoomEnabled() const
{
// By the time anybody calls this, we must have had InitRenderingState called
// already, and so mCompositorOptions should be populated.
MOZ_RELEASE_ASSERT(mCompositorOptions);
return mCompositorOptions->UseAPZ();
}
@@ -2378,36 +2386,41 @@ TabChild::RecvSetDocShellIsActive(const
// channel and the PContent channel, we have an ordering problem. This code
// ensures that we respect the order in which the requests were made and
// ignore stale requests.
if (mLayerObserverEpoch >= aLayerObserverEpoch) {
return IPC_OK();
}
mLayerObserverEpoch = aLayerObserverEpoch;
- MOZ_ASSERT(mPuppetWidget);
- MOZ_ASSERT(mPuppetWidget->GetLayerManager());
- MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
- || mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR);
-
auto clearForcePaint = MakeScopeExit([&] {
// We might force a paint, or we might already have painted and this is a
// no-op. In either case, once we exit this scope, we need to alert the
// ProcessHangMonitor that we've finished responding to what might have
// been a request to force paint. This is so that the BackgroundHangMonitor
// for force painting can be made to wait again.
if (aIsActive) {
ProcessHangMonitor::ClearForcePaint();
}
});
- // We send the current layer observer epoch to the compositor so that
- // TabParent knows whether a layer update notification corresponds to the
- // latest SetDocShellIsActive request that was made.
- mPuppetWidget->GetLayerManager()->SetLayerObserverEpoch(aLayerObserverEpoch);
+ if (mCompositorOptions) {
+ // Note that |GetLayerManager()| has side-effects in that it creates a layer
+ // manager if one doesn't exist already. Calling it inside a debug-only
+ // assertion is generally bad but in this case we call it unconditionally
+ MOZ_ASSERT(mPuppetWidget);
+ MOZ_ASSERT(mPuppetWidget->GetLayerManager());
+ MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
+ || mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR);
+
+ // We send the current layer observer epoch to the compositor so that
+ // TabParent knows whether a layer update notification corresponds to the
+ // latest SetDocShellIsActive request that was made.
+ mPuppetWidget->GetLayerManager()->SetLayerObserverEpoch(aLayerObserverEpoch);
+ }
// docshell is consider prerendered only if not active yet
mIsPrerendered &= !aIsActive;
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
if (docShell) {
bool wasActive;
docShell->GetIsActive(&wasActive);
if (aIsActive && wasActive) {
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -615,16 +615,17 @@ public:
bool IPCOpen() const { return mIPCOpen; }
bool ParentIsActive() const
{
return mParentIsActive;
}
+ const mozilla::layers::CompositorOptions& GetCompositorOptions() const;
bool AsyncPanZoomEnabled() const;
virtual ScreenIntSize GetInnerSize() override;
// Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
void DoFakeShow(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
const uint64_t& aLayersId,
PRenderFrameChild* aRenderFrame,
--- a/gfx/tests/browser/browser_windowless_troubleshoot_crash.js
+++ b/gfx/tests/browser/browser_windowless_troubleshoot_crash.js
@@ -23,18 +23,22 @@ add_task(function* test_windowlessBrowse
});
webNav.loadURI("about:blank", 0, null, null, null);
yield onLoaded;
let winUtils = webNav.document.defaultView.
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
- is(winUtils.layerManagerType, "None", "windowless browser's layerManagerType should be 'None'");
-
+ try {
+ is(winUtils.layerManagerType, "None", "windowless browser's layerManagerType should be 'None'");
+ } catch (e) {
+ // The windowless browser may not have a layermanager at all yet, and that's ok.
+ // The troubleshooting code similarly skips over windows with no layer managers.
+ }
ok(true, "not crashed");
var Troubleshoot = Cu.import("resource://gre/modules/Troubleshoot.jsm", {}).Troubleshoot;
var data = yield new Promise((resolve, reject) => {
Troubleshoot.snapshot((data) => {
resolve(data);
});
});
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -584,33 +584,37 @@ PuppetWidget::ExecuteNativeKeyBinding(
}
LayerManager*
PuppetWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
LayersBackend aBackendHint,
LayerManagerPersistence aPersistence)
{
if (!mLayerManager) {
- if (gfxPrefs::WebRenderEnabled()) {
+ if (!mTabChild) {
+ return nullptr;
+ }
+ if (mTabChild->GetCompositorOptions().UseWebRender()) {
mLayerManager = new WebRenderLayerManager(this);
} else {
mLayerManager = new ClientLayerManager(this);
}
}
ShadowLayerForwarder* lf = mLayerManager->AsShadowForwarder();
if (lf && !lf->HasShadowManager() && aShadowManager) {
lf->SetShadowManager(aShadowManager);
}
return mLayerManager;
}
LayerManager*
PuppetWidget::RecreateLayerManager(PLayerTransactionChild* aShadowManager)
{
- if (gfxPrefs::WebRenderEnabled()) {
+ MOZ_ASSERT(mTabChild);
+ if (mTabChild->GetCompositorOptions().UseWebRender()) {
mLayerManager = new WebRenderLayerManager(this);
} else {
mLayerManager = new ClientLayerManager(this);
}
if (ShadowLayerForwarder* lf = mLayerManager->AsShadowForwarder()) {
lf->SetShadowManager(aShadowManager);
}
return mLayerManager;