Bug 1345017 - Discard compositor animations on the next layer transaction, r?kats
Animations in content side could be removed easily by changing CSS, but the
CompositorAnimationStorage in parent side doesn't get updated. Therefore,
we store the layer's CompositorAnimationsId before layer is destroyed in
WebRenderLayerManager and then send out these discarded ids to parent on
the next layer transaction.
MozReview-Commit-ID: D4kbYsgLl4P
--- a/gfx/layers/ipc/WebRenderMessages.ipdlh
+++ b/gfx/layers/ipc/WebRenderMessages.ipdlh
@@ -36,16 +36,21 @@ struct OpAddExternalImage {
uint64_t externalImageId;
ImageKey key;
};
struct OpAddCompositorAnimations {
CompositorAnimations data;
};
+struct OpRemoveCompositorAnimations {
+ uint64_t id;
+};
+
union WebRenderParentCommand {
OpAddExternalImage;
CompositableOperation;
OpAddCompositorAnimations;
+ OpRemoveCompositorAnimations;
};
} // namespace
} // namespace
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -424,16 +424,28 @@ WebRenderBridgeParent::ProcessWebRenderC
CompositorAnimationStorage* storage =
mCompositorBridge->GetAnimationStorage(id);
if (storage) {
storage->SetAnimations(data.id(), data.animations());
}
}
break;
}
+ case WebRenderParentCommand::TOpRemoveCompositorAnimations: {
+ const OpRemoveCompositorAnimations& op = cmd.get_OpRemoveCompositorAnimations();
+ if (op.id()) {
+ uint64_t id = mWidget ? 0 : mPipelineId.mHandle;
+ CompositorAnimationStorage* storage =
+ mCompositorBridge->GetAnimationStorage(id);
+ if (storage) {
+ storage->ClearById(op.id());
+ }
+ }
+ break;
+ }
default: {
// other commands are handle on the child
break;
}
}
}
if (mWidget) {
LayoutDeviceIntSize size = mWidget->GetClientSize();
--- a/gfx/layers/wr/WebRenderContainerLayer.cpp
+++ b/gfx/layers/wr/WebRenderContainerLayer.cpp
@@ -32,17 +32,19 @@ WebRenderContainerLayer::RenderLayer(wr:
printf_stderr("ContainerLayer %p using bounds=%s, overflow=%s, transform=%s, mix-blend-mode=%s\n",
this->GetLayer(),
Stringify(relBounds).c_str(),
Stringify(overflow).c_str(),
Stringify(transform).c_str(),
Stringify(mixBlendMode).c_str());
}
- if (GetCompositorAnimationsId()) {
+ if (GetAnimations().Length()) {
+ MOZ_ASSERT(GetCompositorAnimationsId());
+
CompositorAnimations anim;
anim.animations() = GetAnimations();
anim.id() = GetCompositorAnimationsId();
WrBridge()->AddWebRenderParentCommand(OpAddCompositorAnimations(anim));
float* maybeOpacity = HasOpacityAnimation() ? nullptr : &opacity;
gfx::Matrix4x4* maybeTransform = HasTransformAnimation() ? nullptr : &transform;
aBuilder.PushStackingContext(wr::ToWrRect(relBounds),
--- a/gfx/layers/wr/WebRenderContainerLayer.h
+++ b/gfx/layers/wr/WebRenderContainerLayer.h
@@ -20,16 +20,21 @@ public:
: ContainerLayer(aManager, static_cast<WebRenderLayer*>(this))
{
MOZ_COUNT_CTOR(WebRenderContainerLayer);
}
protected:
virtual ~WebRenderContainerLayer()
{
+ if (GetAnimations().Length()) {
+ mManager->AsWebRenderLayerManager()->
+ AddCompositorAnimationsIdForDiscard(GetCompositorAnimationsId());
+ }
+
ContainerLayer::RemoveAllChildren();
MOZ_COUNT_DTOR(WebRenderContainerLayer);
}
public:
Layer* GetLayer() override { return this; }
void RenderLayer(wr::DisplayListBuilder& aBuilder) override;
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -307,16 +307,17 @@ WebRenderLayerManager::EndTransaction(Dr
// Since we don't do repeat transactions right now, just set the time
mAnimationReadyTime = TimeStamp::Now();
LayoutDeviceIntSize size = mWidget->GetClientSize();
if (!WrBridge()->DPBegin(size.ToUnknownSize())) {
return;
}
+ DiscardCompositorAnimations();
mRoot->StartPendingAnimations(mAnimationReadyTime);
wr::DisplayListBuilder builder(WrBridge()->GetPipeline());
WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer(builder);
bool sync = mTarget != nullptr;
mLatestTransactionId = mTransactionIdAllocator->GetTransactionId();
@@ -405,16 +406,32 @@ WebRenderLayerManager::DiscardImages()
{
for (auto key : mImageKeys) {
WrBridge()->SendDeleteImage(key);
}
mImageKeys.clear();
}
void
+WebRenderLayerManager::AddCompositorAnimationsIdForDiscard(uint64_t aId)
+{
+ mDiscardedCompositorAnimationsIds.push_back(aId);
+}
+
+void
+WebRenderLayerManager::DiscardCompositorAnimations()
+{
+ for (auto id : mDiscardedCompositorAnimationsIds) {
+ WrBridge()->AddWebRenderParentCommand(OpRemoveCompositorAnimations(id));
+ }
+ mDiscardedCompositorAnimationsIds.clear();
+}
+
+
+void
WebRenderLayerManager::Hold(Layer* aLayer)
{
mKeepAlive.AppendElement(aLayer);
}
void
WebRenderLayerManager::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
{
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -143,32 +143,38 @@ public:
void* GetPaintedLayerCallbackData() const
{ return mPaintedLayerCallbackData; }
// adds an imagekey to a list of keys that will be discarded on the next
// transaction or destruction
void AddImageKeyForDiscard(wr::ImageKey);
void DiscardImages();
+ // Before destroying a layer with animations, add its compositorAnimationsId
+ // to a list of ids that will be discarded on the next transaction
+ void AddCompositorAnimationsIdForDiscard(uint64_t aId);
+ void DiscardCompositorAnimations();
+
WebRenderBridgeChild* WrBridge() const { return mWrChild; }
void Hold(Layer* aLayer);
private:
/**
* Take a snapshot of the parent context, and copy
* it into mTarget.
*/
void MakeSnapshotIfRequired(LayoutDeviceIntSize aSize);
void ClearLayer(Layer* aLayer);
private:
nsIWidget* MOZ_NON_OWNING_REF mWidget;
std::vector<wr::ImageKey> mImageKeys;
+ std::vector<uint64_t> mDiscardedCompositorAnimationsIds;
/* PaintedLayer callbacks; valid at the end of a transaciton,
* while rendering */
DrawPaintedLayerCallback mPaintedLayerCallback;
void *mPaintedLayerCallbackData;
RefPtr<WebRenderBridgeChild> mWrChild;