Bug 1320628 - Fix background tab crash when e10s is enabled r=nical?

This commit is contained in:
sotaro
2016-11-30 11:59:14 +09:00
parent 3a64eef17f
commit bce64e2754
12 changed files with 129 additions and 26 deletions

View File

@@ -2330,9 +2330,7 @@ TabChild::RecvSetDocShellIsActive(const bool& aIsActive,
// 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.
if (ClientLayerManager* clm = mPuppetWidget->GetLayerManager()->AsClientLayerManager()) {
clm->SetLayerObserverEpoch(aLayerObserverEpoch);
}
mPuppetWidget->GetLayerManager()->SetLayerObserverEpoch(aLayerObserverEpoch);
// docshell is consider prerendered only if not active yet
mIsPrerendered &= !aIsActive;
@@ -2800,12 +2798,10 @@ TabChild::DidComposite(uint64_t aTransactionId,
{
MOZ_ASSERT(mPuppetWidget);
MOZ_ASSERT(mPuppetWidget->GetLayerManager());
MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() ==
LayersBackend::LAYERS_CLIENT);
MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
|| mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR);
RefPtr<ClientLayerManager> manager = mPuppetWidget->GetLayerManager()->AsClientLayerManager();
manager->DidComposite(aTransactionId, aCompositeStart, aCompositeEnd);
mPuppetWidget->GetLayerManager()->DidComposite(aTransactionId, aCompositeStart, aCompositeEnd);
}
void
@@ -2839,11 +2835,10 @@ TabChild::ClearCachedResources()
{
MOZ_ASSERT(mPuppetWidget);
MOZ_ASSERT(mPuppetWidget->GetLayerManager());
MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() ==
LayersBackend::LAYERS_CLIENT);
MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
|| mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR);
ClientLayerManager *manager = mPuppetWidget->GetLayerManager()->AsClientLayerManager();
manager->ClearCachedResources();
mPuppetWidget->GetLayerManager()->ClearCachedResources();
}
void
@@ -2851,8 +2846,8 @@ TabChild::InvalidateLayers()
{
MOZ_ASSERT(mPuppetWidget);
MOZ_ASSERT(mPuppetWidget->GetLayerManager());
MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() ==
LayersBackend::LAYERS_CLIENT);
MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT
|| mPuppetWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_WR);
RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
FrameLayerBuilder::InvalidateAllLayers(lm);

View File

@@ -678,6 +678,12 @@ public:
return count;
}
virtual void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch) {}
virtual void DidComposite(uint64_t aTransactionId,
const mozilla::TimeStamp& aCompositeStart,
const mozilla::TimeStamp& aCompositeEnd) {}
protected:
RefPtr<Layer> mRoot;
gfx::UserData mUserData;

View File

@@ -175,9 +175,9 @@ public:
virtual bool RequestOverfill(mozilla::dom::OverfillCallback* aCallback) override;
virtual void RunOverfillCallback(const uint32_t aOverfill) override;
void DidComposite(uint64_t aTransactionId,
const mozilla::TimeStamp& aCompositeStart,
const mozilla::TimeStamp& aCompositeEnd);
virtual void DidComposite(uint64_t aTransactionId,
const mozilla::TimeStamp& aCompositeStart,
const mozilla::TimeStamp& aCompositeEnd) override;
virtual bool AreComponentAlphaLayersEnabled() override;
@@ -224,7 +224,7 @@ public:
void SetNextPaintSyncId(int32_t aSyncId);
void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch);
virtual void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch) override;
class DidCompositeObserver {
public:

View File

@@ -1572,7 +1572,7 @@ CompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t& aPipelineId,
RefPtr<gl::GLContext> glc(gl::GLContextProvider::CreateForCompositorWidget(mWidget, true));
mCompositor = new WebRenderCompositorOGL(glc.get());
mWRBridge = new WebRenderBridgeParent(aPipelineId,
mWRBridge = new WebRenderBridgeParent(this, aPipelineId,
mWidget, glc.get(), nullptr, mCompositor.get());
mWRBridge.get()->AddRef(); // IPDL reference
MonitorAutoLock lock(*sIndirectLayerTreesLock);

View File

@@ -122,6 +122,8 @@ public:
virtual mozilla::ipc::IPCResult RecvSyncWithCompositor() override { return IPC_OK(); }
virtual void ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive) = 0;
// HostIPCAllocator
virtual base::ProcessId GetChildProcessId() override;
virtual void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) override;
@@ -257,6 +259,8 @@ public:
PCompositorWidgetParent* AllocPCompositorWidgetParent(const CompositorWidgetInitData& aInitData) override;
bool DeallocPCompositorWidgetParent(PCompositorWidgetParent* aActor) override;
void ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive) override { }
/**
* Request that the compositor be recreated due to a shared device reset.
* This must be called on the main thread, and blocks until a task posted

View File

@@ -213,7 +213,7 @@ CrossProcessCompositorBridgeParent::AllocPWebRenderBridgeParent(const uint64_t&
WebRenderBridgeParent* root = sIndirectLayerTrees[cbp->RootLayerTreeId()].mWRBridge.get();
WebRenderBridgeParent* parent = new WebRenderBridgeParent(
aPipelineId, nullptr, root->GLContext(), root->WindowState(), root->Compositor());
this, aPipelineId, nullptr, root->GLContext(), root->WindowState(), root->Compositor());
parent->AddRef(); // IPDL reference
sIndirectLayerTrees[aPipelineId].mWRBridge = parent;
*aTextureFactoryIdentifier = parent->Compositor()->GetTextureFactoryIdentifier();
@@ -567,5 +567,19 @@ CrossProcessCompositorBridgeParent::UpdatePaintTime(LayerTransactionParent* aLay
state->mParent->UpdatePaintTime(aLayerTree, aPaintTime);
}
void
CrossProcessCompositorBridgeParent::ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive)
{
MOZ_ASSERT(aLayersId != 0);
CompositorBridgeParent::LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
if (!state || !state->mParent) {
return;
}
Unused << state->mParent->SendObserveLayerUpdate(aLayersId, aEpoch, aActive);
}
} // namespace layers
} // namespace mozilla

View File

@@ -158,6 +158,8 @@ public:
TextureFactoryIdentifier* aTextureFactoryIdentifier) override;
bool DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor) override;
void ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive) override;
protected:
void OnChannelConnected(int32_t pid) override {
mCompositorThreadHolder = CompositorThreadHolder::GetSingleton();

View File

@@ -37,6 +37,8 @@ parent:
sync DPGetSnapshot(PTexture texture, IntRect dirtyRect);
async AddExternalImageId(uint64_t aImageId, uint64_t aAsyncContainerId);
async RemoveExternalImageId(uint64_t aImageId);
async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
async ClearCachedResources();
async Shutdown();
child:

View File

@@ -10,6 +10,7 @@
#include "GLContext.h"
#include "GLContextProvider.h"
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorVsyncScheduler.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/TextureHost.h"
@@ -21,19 +22,23 @@ namespace layers {
using namespace mozilla::gfx;
WebRenderBridgeParent::WebRenderBridgeParent(const uint64_t& aPipelineId,
WebRenderBridgeParent::WebRenderBridgeParent(CompositorBridgeParentBase* aCompositorBridge,
const uint64_t& aPipelineId,
widget::CompositorWidget* aWidget,
gl::GLContext* aGlContext,
wrwindowstate* aWrWindowState,
layers::Compositor* aCompositor)
: mPipelineId(aPipelineId)
: mCompositorBridge(aCompositorBridge)
, mPipelineId(aPipelineId)
, mWidget(aWidget)
, mWRState(nullptr)
, mGLContext(aGlContext)
, mWRWindowState(aWrWindowState)
, mCompositor(aCompositor)
, mChildLayerObserverEpoch(0)
, mParentLayerObserverEpoch(0)
, mDestroyed(false)
, mEpoch(0)
, mWREpoch(0)
{
MOZ_ASSERT(mGLContext);
MOZ_ASSERT(mCompositor);
@@ -206,9 +211,13 @@ WebRenderBridgeParent::ProcessWebrenderCommands(InfallibleTArray<WebRenderComman
NS_RUNTIMEABORT("not reached");
}
}
wr_dp_end(mWRWindowState, mWRState, mEpoch++);
wr_dp_end(mWRWindowState, mWRState, mWREpoch++);
ScheduleComposition();
DeleteOldImages();
if (ShouldParentObserveEpoch()) {
mCompositorBridge->ObserveLayerUpdate(mPipelineId, GetChildLayerObserverEpoch(), true);
}
}
mozilla::ipc::IPCResult
@@ -315,6 +324,20 @@ WebRenderBridgeParent::RecvRemoveExternalImageId(const uint64_t& aImageId)
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch)
{
mChildLayerObserverEpoch = aLayerObserverEpoch;
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvClearCachedResources()
{
mCompositorBridge->ObserveLayerUpdate(mPipelineId, GetChildLayerObserverEpoch(), false);
return IPC_OK();
}
void
WebRenderBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
{
@@ -391,6 +414,18 @@ WebRenderBridgeParent::ClearResources()
mCompositorScheduler = nullptr;
}
mGLContext = nullptr;
mCompositorBridge = nullptr;
}
bool
WebRenderBridgeParent::ShouldParentObserveEpoch()
{
if (mParentLayerObserverEpoch == mChildLayerObserverEpoch) {
return false;
}
mParentLayerObserverEpoch = mChildLayerObserverEpoch;
return true;
}
} // namespace layers

View File

@@ -25,6 +25,7 @@ class CompositorWidget;
namespace layers {
class Compositor;
class CompositorBridgeParentBase;
class CompositorVsyncScheduler;
class WebRenderBridgeParent final : public PWebRenderBridgeParent
@@ -33,7 +34,8 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderBridgeParent)
public:
WebRenderBridgeParent(const uint64_t& aPipelineId,
WebRenderBridgeParent(CompositorBridgeParentBase* aCompositorBridge,
const uint64_t& aPipelineId,
widget::CompositorWidget* aWidget,
gl::GLContext* aGlContext,
wrwindowstate* aWrWindowState,
@@ -70,6 +72,10 @@ public:
const uint64_t& aAsyncContainerId) override;
mozilla::ipc::IPCResult RecvRemoveExternalImageId(const uint64_t& aImageId) override;
mozilla::ipc::IPCResult RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch) override;
mozilla::ipc::IPCResult RecvClearCachedResources() override;
void ActorDestroy(ActorDestroyReason aWhy) override;
void Destroy();
@@ -85,8 +91,11 @@ protected:
void ProcessWebrenderCommands(InfallibleTArray<WebRenderCommand>& commands);
void ScheduleComposition();
void ClearResources();
uint64_t GetChildLayerObserverEpoch() const { return mChildLayerObserverEpoch; }
bool ShouldParentObserveEpoch();
private:
CompositorBridgeParentBase* mCompositorBridge;
uint64_t mPipelineId;
RefPtr<widget::CompositorWidget> mWidget;
wrstate* mWRState;
@@ -97,8 +106,15 @@ private:
std::vector<WRImageKey> mKeysToDelete;
nsDataHashtable<nsUint64HashKey, uint64_t> mExternalImageIds;
// These fields keep track of the latest layer observer epoch values in the child and the
// parent. mChildLayerObserverEpoch is the latest epoch value received from the child.
// mParentLayerObserverEpoch is the latest epoch value that we have told TabParent about
// (via ObserveLayerUpdate).
uint64_t mChildLayerObserverEpoch;
uint64_t mParentLayerObserverEpoch;
bool mDestroyed;
uint32_t mEpoch;
uint32_t mWREpoch;
};
} // namespace layers

View File

@@ -306,6 +306,26 @@ WebRenderLayerManager::DiscardImages()
mImageKeys.clear();
}
void
WebRenderLayerManager::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
{
WRBridge()->SendSetLayerObserverEpoch(aLayerObserverEpoch);
}
void
WebRenderLayerManager::DidComposite(uint64_t aTransactionId,
const mozilla::TimeStamp& aCompositeStart,
const mozilla::TimeStamp& aCompositeEnd)
{
// XXX Add DidComposite handling
}
void
WebRenderLayerManager::ClearCachedResources(Layer* aSubtree)
{
WRBridge()->SendClearCachedResources();
}
void
WebRenderLayerManager::SetRoot(Layer* aLayer)
{

View File

@@ -113,6 +113,15 @@ public:
virtual bool NeedsWidgetInvalidation() override { return true; }
virtual void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch) override;
virtual void DidComposite(uint64_t aTransactionId,
const mozilla::TimeStamp& aCompositeStart,
const mozilla::TimeStamp& aCompositeEnd) override;
virtual void ClearCachedResources(Layer* aSubtree = nullptr) override;
DrawPaintedLayerCallback GetPaintedLayerCallback() const
{ return mPaintedLayerCallback; }