Bug 1345017 - Discard compositor animations on the next layer transaction, r?kats draft
authorpeter chang <pchang@mozilla.com>
Fri, 14 Apr 2017 11:58:42 +0800
changeset 564067 a11c4fa227dbe0d7c483720ec29d0dda78c3c081
parent 564066 85d1de0c7e17cafde693932c8e64c14556a69c25
child 564068 ab942c044d69f36f9da5e70873771fcd60c6ed5f
push id54512
push userbmo:howareyou322@gmail.com
push dateTue, 18 Apr 2017 08:40:13 +0000
reviewerskats
bugs1345017
milestone55.0a1
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
gfx/layers/ipc/WebRenderMessages.ipdlh
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderContainerLayer.cpp
gfx/layers/wr/WebRenderContainerLayer.h
gfx/layers/wr/WebRenderLayerManager.cpp
gfx/layers/wr/WebRenderLayerManager.h
--- 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;