Bug 779598 - Prerender descendant frames in prerendered preserve-3d frame. r?mattwoodrow draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Tue, 24 Jul 2018 13:12:26 +0900
changeset 821852 3fe2c6114b6c8bb7b05aca321b41125e87c9d9db
parent 821851 07ee873392ad5f2aebea34cda321bcb695938dbf
push id117200
push userhikezoe@mozilla.com
push dateTue, 24 Jul 2018 04:13:09 +0000
reviewersmattwoodrow
bugs779598
milestone63.0a1
Bug 779598 - Prerender descendant frames in prerendered preserve-3d frame. r?mattwoodrow MozReview-Commit-ID: 819nIPeNIh4
layout/generic/nsFrame.cpp
layout/generic/nsIFrame.h
layout/painting/nsDisplayList.cpp
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1643,16 +1643,39 @@ nsIFrame::In3DContextAndBackfaceIsHidden
   // While both tests fail most of the time, test BackfaceIsHidden()
   // first since it's likely to fail faster.
   const nsStyleDisplay* disp = StyleDisplay();
   return BackfaceIsHidden(disp) &&
          Combines3DTransformWithAncestors(disp);
 }
 
 bool
+nsIFrame::IsInPrerendered3DContext(nsDisplayListBuilder* aBuilder) const
+{
+  if (!Combines3DTransformWithAncestors()) {
+    return false;
+  }
+
+  nsIFrame* parent = GetInFlowParent();
+  MOZ_ASSERT(parent && parent->Extend3DContext());
+
+  DisplayItemDataArray& array = parent->DisplayItemData();
+  for (auto data: array) {
+    DisplayItemData::AssertDisplayItemData(data);
+    if (data->GetItem() &&
+        data->GetItem()->CanUseAsyncAnimations(aBuilder) &&
+        data->GetDisplayItemKey() ==
+          static_cast<uint32_t>(DisplayItemType::TYPE_TRANSFORM)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool
 nsIFrame::HasPerspective(const nsStyleDisplay* aStyleDisplay) const
 {
   MOZ_ASSERT(aStyleDisplay == StyleDisplay());
   if (!IsTransformed(aStyleDisplay)) {
     return false;
   }
   nsIFrame* containingBlock = GetContainingBlock(SKIP_SCROLLED_FRAME, aStyleDisplay);
   if (!containingBlock) {
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1854,16 +1854,21 @@ public:
                         mozilla::EffectSet* aEffectSet = nullptr) const {
     return Combines3DTransformWithAncestors(aStyleDisplay) &&
            !Extend3DContext(aStyleDisplay, aEffectSet);
   }
   bool IsPreserve3DLeaf(mozilla::EffectSet* aEffectSet = nullptr) const {
     return IsPreserve3DLeaf(StyleDisplay(), aEffectSet);
   }
 
+  /**
+   * Returns true if this frame is a child of prerendered preserve-3d frame.
+   */
+  bool IsInPrerendered3DContext(nsDisplayListBuilder* aBuilder) const;
+
   bool HasPerspective(const nsStyleDisplay* aStyleDisplay) const;
   bool HasPerspective() const {
     return HasPerspective(StyleDisplay());
   }
 
   bool ChildrenHavePerspective(const nsStyleDisplay* aStyleDisplay) const;
   bool ChildrenHavePerspective() const {
     return ChildrenHavePerspective(StyleDisplay());
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -8022,16 +8022,20 @@ nsDisplayTransform::CanUseAsyncAnimation
   return mAllowAsyncAnimation;
 }
 
 /* static */ auto
 nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
                                                       nsIFrame* aFrame,
                                                       nsRect* aDirtyRect) -> PrerenderDecision
 {
+  // Prerender if the frame is a child of prerendered preserve-3d context.
+  if (aFrame->IsInPrerendered3DContext(aBuilder)) {
+    return FullPrerender;
+  }
   // Elements whose transform has been modified recently, or which
   // have a compositor-animated transform, can be prerendered. An element
   // might have only just had its transform animated in which case
   // the ActiveLayerManager may not have been notified yet.
   if (!ActiveLayerTracker::IsStyleMaybeAnimated(aFrame, eCSSProperty_transform) &&
       !EffectCompositor::HasAnimationsForCompositor(aFrame,
                                                     eCSSProperty_transform)) {
     EffectCompositor::SetPerformanceWarning(