Bug 1519546, part 7 - Gather EffectsInfo for remote browsers in a paint and apply them. r=mattwoodrow
authorRyan Hunt <rhunt@eqrion.net>
Fri, 24 May 2019 09:28:23 -0500
changeset 476556 b81cf35a573e1e3054dd792b8ab1ee0824139435
parent 476555 4df5fa6fa785961229e7e0a7a0ebbab625192f24
child 476557 ac0ad5d8e9a57c716e392c59b655853a728911b4
push id113291
push userrhunt@eqrion.net
push dateSun, 02 Jun 2019 16:51:17 +0000
treeherdermozilla-inbound@ac0ad5d8e9a5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1519546
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1519546, part 7 - Gather EffectsInfo for remote browsers in a paint and apply them. r=mattwoodrow WebRender support will be finished in the following commit. Differential Revision: https://phabricator.services.mozilla.com/D32476
layout/base/nsLayoutUtils.cpp
layout/ipc/RenderFrame.cpp
layout/painting/FrameLayerBuilder.cpp
layout/painting/FrameLayerBuilder.h
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3536,16 +3536,27 @@ void PrintHitTestInfoStats(nsDisplayList
 
   printf(
       "List %p: total items: %d, hit test items: %d, ratio: %f, visible: %d, "
       "special: %d\n",
       &aList, total, hitTest, ratio, visible, special);
 }
 #endif
 
+// Apply a batch of effects updates generated during a paint to their
+// respective remote browsers.
+static void ApplyEffectsUpdates(
+    const nsDataHashtable<nsPtrHashKey<RemoteBrowser>, EffectsInfo>& aUpdates) {
+  for (auto iter = aUpdates.ConstIter(); !iter.Done(); iter.Next()) {
+    auto browser = iter.Key();
+    auto update = iter.Data();
+    browser->UpdateEffects(update);
+  }
+}
+
 nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
                                    nsIFrame* aFrame,
                                    const nsRegion& aDirtyRegion,
                                    nscolor aBackstop,
                                    nsDisplayListBuilderMode aBuilderMode,
                                    PaintFrameFlags aFlags) {
   AUTO_PROFILER_LABEL("nsLayoutUtils::PaintFrame", GRAPHICS);
   typedef RetainedDisplayListBuilder::PartialUpdateResult PartialUpdateResult;
@@ -4084,16 +4095,21 @@ nsresult nsLayoutUtils::PaintFrame(gfxCo
       layerManager->ScheduleComposite();
     }
 
     // Disable partial updates for the following paint as well, as we now have
     // a plugin-specific display list.
     builder.SetDisablePartialUpdates(true);
   }
 
+  // Apply effects updates if we were actually painting
+  if (isForPainting) {
+    ApplyEffectsUpdates(builder.GetEffectUpdates());
+  }
+
   builder.Check();
 
   {
     AUTO_PROFILER_TRACING("Paint", "DisplayListResources", GRAPHICS);
 
     // Flush the list so we don't trigger the IsEmpty-on-destruction assertion
     if (!useRetainedBuilder) {
       list.DeleteAll(&builder);
--- a/layout/ipc/RenderFrame.cpp
+++ b/layout/ipc/RenderFrame.cpp
@@ -16,16 +16,17 @@
 #include "nsStyleStructInlines.h"
 #include "nsSubDocumentFrame.h"
 #include "RenderFrame.h"
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/layers/CompositorBridgeChild.h"
 #include "mozilla/layers/WebRenderLayerManager.h"
 #include "mozilla/layers/WebRenderScrollData.h"
 #include "mozilla/webrender/WebRenderAPI.h"
+#include "mozilla/dom/EffectsInfo.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
 namespace mozilla {
 namespace layout {
 
@@ -212,16 +213,24 @@ already_AddRefed<Layer> nsDisplayRemote:
     NS_WARNING("Remote iframe not rendered");
     return nullptr;
   }
 
   if (!mLayersId.IsValid()) {
     return nullptr;
   }
 
+  if (RefPtr<RemoteBrowser> remoteBrowser =
+          GetFrameLoader()->GetRemoteBrowser()) {
+    // Generate an effects update notifying the browser it is visible
+    aBuilder->AddEffectUpdate(remoteBrowser, EffectsInfo::FullyVisible());
+    // FrameLayerBuilder will take care of notifying the browser when it is no
+    // longer visible
+  }
+
   RefPtr<Layer> layer =
       aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this);
 
   if (!layer) {
     layer = aManager->CreateRefLayer();
   }
   if (!layer || !layer->AsRefLayer()) {
     // Probably a temporary layer manager that doesn't know how to
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -7,16 +7,18 @@
 #include "mozilla/DebugOnly.h"
 
 #include "FrameLayerBuilder.h"
 
 #include "gfxContext.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/PresShell.h"
+#include "mozilla/dom/EffectsInfo.h"
+#include "mozilla/dom/RemoteBrowser.h"
 #include "mozilla/dom/ProfileTimelineMarkerBinding.h"
 #include "mozilla/gfx/Matrix.h"
 #include "ActiveLayerTracker.h"
 #include "BasicLayers.h"
 #include "ImageContainer.h"
 #include "ImageLayers.h"
 #include "LayerTreeInvalidation.h"
 #include "Layers.h"
@@ -29,16 +31,17 @@
 #include "gfxEnv.h"
 #include "gfxUtils.h"
 #include "nsAutoPtr.h"
 #include "nsAnimationManager.h"
 #include "nsDisplayList.h"
 #include "nsDocShell.h"
 #include "nsIScrollableFrame.h"
 #include "nsImageFrame.h"
+#include "nsSubDocumentFrame.h"
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsPrintfCString.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsTransitionManager.h"
 #include "mozilla/LayerTimelineMarker.h"
 
 #include "mozilla/EffectCompositor.h"
@@ -382,26 +385,44 @@ DisplayItemData::~DisplayItemData() {
   sAliveDisplayItemDatas->RemoveEntry(entry);
 
   if (sAliveDisplayItemDatas->Count() == 0) {
     delete sAliveDisplayItemDatas;
     sAliveDisplayItemDatas = nullptr;
   }
 }
 
-void DisplayItemData::ClearAnimationCompositorState() {
+void DisplayItemData::NotifyRemoved() {
   if (mDisplayItemKey > static_cast<uint8_t>(DisplayItemType::TYPE_MAX)) {
     // This is sort of a hack. The display item key has higher bits set, which
     // means that it is not the only display item for the frame.
     // This branch skips separator transforms.
     return;
   }
 
   const DisplayItemType type = GetDisplayItemTypeFromKey(mDisplayItemKey);
 
+  if (type == DisplayItemType::TYPE_REMOTE) {
+    // TYPE_REMOTE doesn't support merging, so access it directly
+    MOZ_ASSERT(mFrameList.Length() == 1);
+    if (mFrameList.Length() != 1) {
+      return;
+    }
+
+    // This is a remote browser that is going away, notify it that it is now
+    // hidden
+    nsIFrame* frame = mFrameList[0];
+    nsSubDocumentFrame* subdoc = static_cast<nsSubDocumentFrame*>(frame);
+    nsFrameLoader* frameLoader = subdoc->FrameLoader();
+    if (frameLoader && frameLoader->GetRemoteBrowser()) {
+      frameLoader->GetRemoteBrowser()->UpdateEffects(
+          mozilla::dom::EffectsInfo::FullyHidden());
+    }
+  }
+
   // FIXME: Bug 1530857: Add background_color.
   if (type != DisplayItemType::TYPE_TRANSFORM &&
       type != DisplayItemType::TYPE_OPACITY) {
     return;
   }
 
   for (nsIFrame* frame : mFrameList) {
     EffectCompositor::ClearIsRunningOnCompositor(frame, type);
@@ -2233,16 +2254,28 @@ void FrameLayerBuilder::RemoveFrameFromL
 
     auto it = std::find(data->mParent->mDisplayItems.begin(),
                         data->mParent->mDisplayItems.end(), data);
     MOZ_ASSERT(it != data->mParent->mDisplayItems.end());
     std::iter_swap(it, data->mParent->mDisplayItems.end() - 1);
     data->mParent->mDisplayItems.pop_back();
   }
 
+  if (aFrame->IsSubDocumentFrame()) {
+    const nsSubDocumentFrame* subdoc =
+        static_cast<const nsSubDocumentFrame*>(aFrame);
+    nsFrameLoader* frameLoader = subdoc->FrameLoader();
+    if (frameLoader && frameLoader->GetRemoteBrowser()) {
+      // This is a remote browser that is going away, notify it that it is now
+      // hidden
+      frameLoader->GetRemoteBrowser()->UpdateEffects(
+          mozilla::dom::EffectsInfo::FullyHidden());
+    }
+  }
+
   arrayCopy.Clear();
   sDestroyedFrame = nullptr;
 }
 
 void FrameLayerBuilder::DidBeginRetainedLayerTransaction(
     LayerManager* aManager) {
   mRetainingManager = aManager;
   LayerManagerData* data = static_cast<LayerManagerData*>(
@@ -2285,17 +2318,17 @@ void FrameLayerBuilder::WillEndTransacti
               did->mDisplayItemKey, did->mFrameList[0], t);
         }
 #endif
         InvalidatePreTransformRect(
             t, did->mGeometry->ComputeInvalidationRegion(), did->mClip,
             GetLastPaintOffset(t), did->mTransform);
       }
 
-      did->ClearAnimationCompositorState();
+      did->NotifyRemoved();
 
       // Remove this item. Swapping it with the last element first is
       // quicker than erasing from the middle.
       if (iter != data->mDisplayItems.end() - 1) {
         std::iter_swap(iter, data->mDisplayItems.end() - 1);
         data->mDisplayItems.pop_back();
       } else {
         data->mDisplayItems.pop_back();
--- a/layout/painting/FrameLayerBuilder.h
+++ b/layout/painting/FrameLayerBuilder.h
@@ -81,17 +81,17 @@ class DisplayItemData final {
   friend class FrameLayerBuilder;
   friend class ContainerState;
 
   uint32_t GetDisplayItemKey() { return mDisplayItemKey; }
   layers::Layer* GetLayer() const { return mLayer; }
   nsDisplayItemGeometry* GetGeometry() const { return mGeometry.get(); }
   const DisplayItemClip& GetClip() const { return mClip; }
   void Invalidate() { mIsInvalid = true; }
-  void ClearAnimationCompositorState();
+  void NotifyRemoved();
   void SetItem(nsPaintedDisplayItem* aItem) { mItem = aItem; }
   nsPaintedDisplayItem* GetItem() const { return mItem; }
   nsIFrame* FirstFrame() const { return mFrameList[0]; }
   layers::BasicLayerManager* InactiveManager() const {
     return mInactiveManager;
   }
 
   bool HasMergedFrames() const { return mFrameList.Length() > 1; }
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -1226,16 +1226,17 @@ void nsDisplayListBuilder::BeginFrame() 
 }
 
 void nsDisplayListBuilder::EndFrame() {
   NS_ASSERTION(!mInInvalidSubtree,
                "Someone forgot to cleanup mInInvalidSubtree!");
   mFrameToAnimatedGeometryRootMap.Clear();
   mAGRBudgetSet.Clear();
   mActiveScrolledRoots.Clear();
+  mEffectsUpdates.Clear();
   FreeClipChains();
   FreeTemporaryItems();
   nsCSSRendering::EndFrameTreesLocked();
 }
 
 void nsDisplayListBuilder::MarkFrameForDisplay(nsIFrame* aFrame,
                                                nsIFrame* aStopAtFrame) {
   mFramesMarkedForDisplay.AppendElement(aFrame);
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -29,16 +29,18 @@
 #include "nsRect.h"
 #include "nsRegion.h"
 #include "nsDisplayListInvalidation.h"
 #include "DisplayItemClipChain.h"
 #include "DisplayListClipState.h"
 #include "LayerState.h"
 #include "FrameMetrics.h"
 #include "ImgDrawResult.h"
+#include "mozilla/dom/EffectsInfo.h"
+#include "mozilla/dom/RemoteBrowser.h"
 #include "mozilla/EffectCompositor.h"
 #include "mozilla/EnumeratedArray.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/gfx/UserData.h"
 #include "mozilla/layers/LayerAttributes.h"
 #include "mozilla/layers/RenderRootBoundary.h"
 #include "mozilla/layers/ScrollableLayerGuid.h"
@@ -424,16 +426,19 @@ class nsDisplayListBuilder {
   typedef nsIWidget::ThemeGeometry ThemeGeometry;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::FrameMetrics FrameMetrics;
   typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
   typedef mozilla::layers::ScrollableLayerGuid::ViewID ViewID;
   typedef mozilla::gfx::CompositorHitTestInfo CompositorHitTestInfo;
   typedef mozilla::gfx::Matrix4x4 Matrix4x4;
   typedef mozilla::Maybe<mozilla::layers::ScrollDirection> MaybeScrollDirection;
+  typedef mozilla::dom::EffectsInfo EffectsInfo;
+  typedef mozilla::layers::LayersId LayersId;
+  typedef mozilla::dom::RemoteBrowser RemoteBrowser;
 
   /**
    * @param aReferenceFrame the frame at the root of the subtree; its origin
    * is the origin of the reference coordinate system for this display list
    * @param aMode encodes what the builder is being used for.
    * @param aBuildCaret whether or not we should include the caret in any
    * display lists that we make.
    */
@@ -1035,16 +1040,25 @@ class nsDisplayListBuilder {
    */
   void AdjustWindowDraggingRegion(nsIFrame* aFrame);
 
   LayoutDeviceIntRegion GetWindowDraggingRegion() const;
 
   void RemoveModifiedWindowRegions();
   void ClearRetainedWindowRegions();
 
+  const nsDataHashtable<nsPtrHashKey<RemoteBrowser>, EffectsInfo>&
+  GetEffectUpdates() const {
+    return mEffectsUpdates;
+  }
+
+  void AddEffectUpdate(RemoteBrowser* aBrowser, EffectsInfo aUpdate) {
+    mEffectsUpdates.Put(aBrowser, aUpdate);
+  }
+
   /**
    * Allocate memory in our arena. It will only be freed when this display list
    * builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
    * destructors are called as soon as the item is no longer used.
    */
   void* Allocate(size_t aSize, DisplayItemType aType);
 
   void Destroy(DisplayItemType aType, void* aPtr);
@@ -1890,16 +1904,18 @@ class nsDisplayListBuilder {
 
   // Area of animated geometry root budget already allocated
   uint32_t mUsedAGRBudget;
   // Set of frames already counted in budget
   nsTHashtable<nsPtrHashKey<nsIFrame>> mAGRBudgetSet;
 
   nsTArray<nsIFrame*> mModifiedFramesDuringBuilding;
 
+  nsDataHashtable<nsPtrHashKey<RemoteBrowser>, EffectsInfo> mEffectsUpdates;
+
   // Relative to mCurrentFrame.
   nsRect mVisibleRect;
   nsRect mDirtyRect;
 
   // Tracked regions used for retained display list.
   WeakFrameRegion mWindowExcludeGlassRegion;
   WeakFrameRegion mRetainedWindowDraggingRegion;
   WeakFrameRegion mRetainedWindowNoDraggingRegion;