Bug 1098266 - Set correct visible rect on nsDisplayOpacity items that are shuffled around during preserve-3d display list wrapping. r=tn, a=sledru
authorRobert O'Callahan <robert@ocallahan.org>
Mon, 24 Nov 2014 14:03:49 +1300
changeset 242305 506962a16ce85f0a000b5ae0b16f4d4a787ac9b6
parent 242304 4fb4aec5a4e042624a36f421bc8f3af541913e6c
child 242306 03db536fff9b8dfe522b2482ede4d9b7711577b2
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn, sledru
bugs1098266
milestone36.0a2
Bug 1098266 - Set correct visible rect on nsDisplayOpacity items that are shuffled around during preserve-3d display list wrapping. r=tn, a=sledru
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/generic/nsFrame.cpp
layout/reftests/bugs/1098266-1-ref.html
layout/reftests/bugs/1098266-1.html
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -3477,16 +3477,23 @@ nsRect nsDisplayWrapList::GetComponentAl
 }
 
 void
 nsDisplayWrapList::SetVisibleRect(const nsRect& aRect)
 {
   mVisibleRect = aRect;
 }
 
+void
+nsDisplayWrapList::SetReferenceFrame(const nsIFrame* aFrame)
+{
+  mReferenceFrame = aFrame;
+  mToReferenceFrame = mFrame->GetOffsetToCrossDoc(mReferenceFrame);
+}
+
 static nsresult
 WrapDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                 nsDisplayList* aList, nsDisplayWrapper* aWrapper) {
   if (!aList->GetTop())
     return NS_OK;
   nsDisplayItem* item = aWrapper->WrapList(aBuilder, aFrame, aList);
   if (!item)
     return NS_ERROR_OUT_OF_MEMORY;
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -2738,16 +2738,18 @@ public:
   void SetOverrideZIndex(int32_t aZIndex)
   {
     mHasZIndexOverride = true;
     mOverrideZIndex = aZIndex;
   }
 
   void SetVisibleRect(const nsRect& aRect);
 
+  void SetReferenceFrame(const nsIFrame* aFrame);
+
   /**
    * This creates a copy of this item, but wrapping aItem instead of
    * our existing list. Only gets called if this item returned nullptr
    * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
    * GetUnderlyingFrame().
    */
   virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
                                            nsDisplayItem* aItem) {
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1791,16 +1791,17 @@ WrapPreserve3DListInternal(nsIFrame* aFr
     // and then flush this list into aOutput by wrapping the whole lot with a single
     // nsDisplayTransform.
 
     if (childFrame->GetParent() &&
         (childFrame->GetParent()->Preserves3DChildren() || childFrame == aFrame)) {
       switch (item->GetType()) {
         case nsDisplayItem::TYPE_TRANSFORM: {
           if (!aTemp->IsEmpty()) {
+            // Flush current aTemp contents
             aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder,
                 aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++));
           }
           // Override item's clipping with our current clip state (if any). Since we're
           // bubbling up a preserve-3d transformed child to a preserve-3d parent,
           // we can be sure the child doesn't have clip state of its own.
           NS_ASSERTION(!item->GetClip().HasClip(), "Unexpected clip on item");
           const DisplayItemClip* clip = aBuilder->ClipState().GetCurrentCombinedClip(aBuilder);
@@ -1814,30 +1815,34 @@ WrapPreserve3DListInternal(nsIFrame* aFr
           nsDisplayWrapList *list = static_cast<nsDisplayWrapList*>(item);
           rv = WrapPreserve3DListInternal(aFrame, aBuilder,
               list->GetChildren(), aOutput, aIndex, aTemp);
           list->~nsDisplayWrapList();
           break;
         }
         case nsDisplayItem::TYPE_OPACITY: {
           if (!aTemp->IsEmpty()) {
+            // Flush current aTemp contents
             aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder,
                 aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++));
           }
           nsDisplayOpacity *opacity = static_cast<nsDisplayOpacity*>(item);
           nsDisplayList output;
           // Call GetChildren, not GetSameCoordinateSystemChildren, because
           // the preserve-3d children of 'opacity' are temporarily not in the
           // same coordinate system as the opacity --- until this wrapping is done.
           rv = WrapPreserve3DListInternal(aFrame, aBuilder,
               opacity->GetChildren(), &output, aIndex, aTemp);
           if (!aTemp->IsEmpty()) {
             output.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder,
                 aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++));
           }
+
+          opacity->SetVisibleRect(output.GetVisibleRect());
+          opacity->SetReferenceFrame(output.GetBottom()->ReferenceFrame());
           opacity->GetChildren()->AppendToTop(&output);
           opacity->UpdateBounds(aBuilder);
           aOutput->AppendToTop(item);
           break;
         }
         default: {
           if (childFrame->StyleDisplay()->BackfaceIsHidden()) {
             if (!aTemp->IsEmpty()) {
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1098266-1-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="position: absolute; transform-style: preserve-3d; transform: perspective(600px) scale(0.166667); opacity:0.3">
+  <div style="position: absolute; background: yellow; width:900px; height:100px; transform: translate3d(0, 3000px, 0px) rotateZ(90deg) scale(5); transform-style: preserve-3d;">
+  </div>
+</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1098266-1.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="position: absolute; transform-style: preserve-3d; transform: perspective(600px) scale(0.166667); ">
+  <div style="position: absolute; background: yellow; width:900px; height:100px; transform: translate3d(0, 3000px, 0px) rotateZ(90deg) scale(5); transform-style: preserve-3d; opacity:0.3">
+  </div>
+</div>
+</body>
+</html>