Commit 6c2c3c6e authored by Timothy Nikkel's avatar Timothy Nikkel
Browse files

Bug 1554373. Handle glass item with retained display lists. r=mattwoodrow

We clear mGlassDisplayItem before a full display list build. We use it so that we only mark the first glass item we encounter with the glass item flag.

For partial builds we use the bool mHasGlassItemDuringPartial to track the same thing, so we only mark one item as glass. Merging handles updating mGlassDisplayItem for partial builds.

So this means that we could have one item marked as a glass item in the old list and one item marked as a glass item in the new list.

If merging doesn't use the existing mGlassDisplayItem then it clears mGlassDisplayItem. If merging uses a new item that is a glass item it calls SetGlassDisplayItem on it, so it will only become the new glass item if there wasn't one there already.

So it is actually possible that both items with the glass flag make it into the final display list. Thus the number of display items in the display list with the glass flag can grow to any number, but it would have to be a very very weird state because the glass item is only allowed to be a themed background item coming from a doc element box frame (one per xul doc near the root).

Differential Revision: https://phabricator.services.mozilla.com/D32558

--HG--
extra : moz-landing-system : lando
parent cfe98553
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@ FRAME_TYPE(ColumnSetWrapper)
FRAME_TYPE(ComboboxControl)
FRAME_TYPE(ComboboxControl)
FRAME_TYPE(ComboboxDisplay)
FRAME_TYPE(ComboboxDisplay)
FRAME_TYPE(Deck)
FRAME_TYPE(Deck)
FRAME_TYPE(DocElementBox)
FRAME_TYPE(DateTimeControl)
FRAME_TYPE(DateTimeControl)
FRAME_TYPE(Details)
FRAME_TYPE(Details)
FRAME_TYPE(FieldSet)
FRAME_TYPE(FieldSet)
+1 −1
Original line number Original line Diff line number Diff line
@@ -23,7 +23,7 @@ FRAME_ID(nsComboboxDisplayFrame, ComboboxDisplay, NotLeaf)
FRAME_ID(nsContinuingTextFrame, Text, Leaf)
FRAME_ID(nsContinuingTextFrame, Text, Leaf)
FRAME_ID(nsDateTimeControlFrame, DateTimeControl, NotLeaf)
FRAME_ID(nsDateTimeControlFrame, DateTimeControl, NotLeaf)
FRAME_ID(nsDeckFrame, Deck, NotLeaf)
FRAME_ID(nsDeckFrame, Deck, NotLeaf)
FRAME_ID(nsDocElementBoxFrame, Box, NotLeaf)
FRAME_ID(nsDocElementBoxFrame, DocElementBox, NotLeaf)
FRAME_ID(nsFieldSetFrame, FieldSet, NotLeaf)
FRAME_ID(nsFieldSetFrame, FieldSet, NotLeaf)
FRAME_ID(nsFileControlFrame, Block, Leaf)
FRAME_ID(nsFileControlFrame, Block, Leaf)
FRAME_ID(nsFirstLetterFrame, Letter, NotLeaf)
FRAME_ID(nsFirstLetterFrame, Letter, NotLeaf)
+24 −0
Original line number Original line Diff line number Diff line
@@ -186,6 +186,11 @@ bool RetainedDisplayListBuilder::PreProcessDisplayList(
        MOZ_RELEASE_ASSERT(aList->mOldItems[i].mItem == item);
        MOZ_RELEASE_ASSERT(aList->mOldItems[i].mItem == item);
        aList->mOldItems[i].mItem = nullptr;
        aList->mOldItems[i].mItem = nullptr;
      }
      }

      if (item->IsGlassItem() && item == mBuilder.GetGlassDisplayItem()) {
        mBuilder.ClearGlassDisplayItem();
      }

      item->Destroy(&mBuilder);
      item->Destroy(&mBuilder);


      i++;
      i++;
@@ -449,6 +454,17 @@ class MergeState {
          oldItem->SetBuildingRect(aNewItem->GetBuildingRect());
          oldItem->SetBuildingRect(aNewItem->GetBuildingRect());
        }
        }


        if (destItem == aNewItem) {
          if (oldItem->IsGlassItem() &&
              oldItem == mBuilder->Builder()->GetGlassDisplayItem()) {
            mBuilder->Builder()->ClearGlassDisplayItem();
          }
        }  // aNewItem can't be the glass item on the builder yet.

        if (destItem->IsGlassItem()) {
          mBuilder->Builder()->SetGlassDisplayItem(destItem);
        }

        MergeChildLists(aNewItem, oldItem, destItem);
        MergeChildLists(aNewItem, oldItem, destItem);


        AutoTArray<MergedListIndex, 2> directPredecessors =
        AutoTArray<MergedListIndex, 2> directPredecessors =
@@ -465,6 +481,9 @@ class MergeState {
      }
      }
    }
    }
    mResultIsModified = true;
    mResultIsModified = true;
    if (aNewItem->IsGlassItem()) {
      mBuilder->Builder()->SetGlassDisplayItem(aNewItem);
    }
    return Some(AddNewNode(aNewItem, Nothing(), Span<MergedListIndex>(),
    return Some(AddNewNode(aNewItem, Nothing(), Span<MergedListIndex>(),
                           aPreviousItem));
                           aPreviousItem));
  }
  }
@@ -638,6 +657,11 @@ class MergeState {
                      nsTArray<MergedListIndex>&& aDirectPredecessors) {
                      nsTArray<MergedListIndex>&& aDirectPredecessors) {
    nsDisplayItem* item = mOldItems[aNode.val].mItem;
    nsDisplayItem* item = mOldItems[aNode.val].mItem;
    if (mOldItems[aNode.val].IsChanged() || HasModifiedFrame(item)) {
    if (mOldItems[aNode.val].IsChanged() || HasModifiedFrame(item)) {
      if (item && item->IsGlassItem() &&
          item == mBuilder->Builder()->GetGlassDisplayItem()) {
        mBuilder->Builder()->ClearGlassDisplayItem();
      }

      mOldItems[aNode.val].Discard(mBuilder, std::move(aDirectPredecessors));
      mOldItems[aNode.val].Discard(mBuilder, std::move(aDirectPredecessors));
      mResultIsModified = true;
      mResultIsModified = true;
    } else {
    } else {
+39 −0
Original line number Original line Diff line number Diff line
@@ -1271,6 +1271,41 @@ void nsDisplayListBuilder::MarkFrameForDisplayIfVisible(
  }
  }
}
}


void nsDisplayListBuilder::SetGlassDisplayItem(nsDisplayItem* aItem) {
  // Web pages or extensions could trigger the "Multiple glass backgrounds
  // found?" warning by using -moz-appearance:win-borderless-glass etc on their
  // own elements (as long as they are DocElementBoxFrames, which is rare as
  // each xul doc only gets one near the root). We only care about first one,
  // since that will be the background of the root window.

  if (IsPartialUpdate()) {
    if (aItem->Frame()->IsDocElementBoxFrame()) {
#ifdef DEBUG
      if (mHasGlassItemDuringPartial) {
        NS_WARNING("Multiple glass backgrounds found?");
      } else
#endif
      if (!mHasGlassItemDuringPartial) {
        mHasGlassItemDuringPartial = true;
        aItem->SetIsGlassItem();
      }
    }
    return;
  }

  if (aItem->Frame()->IsDocElementBoxFrame()) {
#ifdef DEBUG
    if (mGlassDisplayItem) {
      NS_WARNING("Multiple glass backgrounds found?");
    } else
#endif
    if (!mGlassDisplayItem) {
      mGlassDisplayItem = aItem;
      mGlassDisplayItem->SetIsGlassItem();
    }
  }
}

bool nsDisplayListBuilder::NeedToForceTransparentSurfaceForItem(
bool nsDisplayListBuilder::NeedToForceTransparentSurfaceForItem(
    nsDisplayItem* aItem) {
    nsDisplayItem* aItem) {
  return aItem == mGlassDisplayItem || aItem->ClearsBackground();
  return aItem == mGlassDisplayItem || aItem->ClearsBackground();
@@ -2229,12 +2264,16 @@ void nsDisplayListBuilder::RemoveModifiedWindowRegions() {
  mRetainedWindowDraggingRegion.RemoveModifiedFramesAndRects();
  mRetainedWindowDraggingRegion.RemoveModifiedFramesAndRects();
  mRetainedWindowNoDraggingRegion.RemoveModifiedFramesAndRects();
  mRetainedWindowNoDraggingRegion.RemoveModifiedFramesAndRects();
  mWindowExcludeGlassRegion.RemoveModifiedFramesAndRects();
  mWindowExcludeGlassRegion.RemoveModifiedFramesAndRects();

  mHasGlassItemDuringPartial = false;
}
}


void nsDisplayListBuilder::ClearRetainedWindowRegions() {
void nsDisplayListBuilder::ClearRetainedWindowRegions() {
  mRetainedWindowDraggingRegion.Clear();
  mRetainedWindowDraggingRegion.Clear();
  mRetainedWindowNoDraggingRegion.Clear();
  mRetainedWindowNoDraggingRegion.Clear();
  mWindowExcludeGlassRegion.Clear();
  mWindowExcludeGlassRegion.Clear();

  mGlassDisplayItem = nullptr;
}
}


const uint32_t gWillChangeAreaMultiplier = 3;
const uint32_t gWillChangeAreaMultiplier = 3;
+12 −11
Original line number Original line Diff line number Diff line
@@ -1602,17 +1602,9 @@ class nsDisplayListBuilder {
   */
   */
  void ClearWindowOpaqueRegion() { mWindowOpaqueRegion.SetEmpty(); }
  void ClearWindowOpaqueRegion() { mWindowOpaqueRegion.SetEmpty(); }


  void SetGlassDisplayItem(nsDisplayItem* aItem) {
  void SetGlassDisplayItem(nsDisplayItem* aItem);
    if (mGlassDisplayItem) {
  void ClearGlassDisplayItem() { mGlassDisplayItem = nullptr; }
      // Web pages or extensions could trigger this by using
  nsDisplayItem* GetGlassDisplayItem() { return mGlassDisplayItem; }
      // -moz-appearance:win-borderless-glass etc on their own elements.
      // Keep the first one, since that will be the background of the root
      // window
      NS_WARNING("Multiple glass backgrounds found?");
    } else {
      mGlassDisplayItem = aItem;
    }
  }


  bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem);
  bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem);


@@ -1920,7 +1912,12 @@ class nsDisplayListBuilder {
  nsRegion mWindowOpaqueRegion;
  nsRegion mWindowOpaqueRegion;


  // The display item for the Windows window glass background, if any
  // The display item for the Windows window glass background, if any
  // Set during full display list builds or during display list merging only,
  // partial display list builds don't touch this.
  nsDisplayItem* mGlassDisplayItem;
  nsDisplayItem* mGlassDisplayItem;
  // If we've encountered a glass item yet, only used during partial display
  // list builds.
  bool mHasGlassItemDuringPartial;
  // A temporary list that we append scroll info items to while building
  // A temporary list that we append scroll info items to while building
  // display items for the contents of frames with SVG effects.
  // display items for the contents of frames with SVG effects.
  // Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
  // Only non-null when ShouldBuildScrollInfoItemsForHoisting() is true.
@@ -2731,6 +2728,9 @@ class nsDisplayItem : public nsDisplayItemBase {
  void SetPainted() { mItemFlags += ItemFlag::Painted; }
  void SetPainted() { mItemFlags += ItemFlag::Painted; }
#endif
#endif


  void SetIsGlassItem() { mItemFlags += ItemFlag::IsGlassItem; }
  bool IsGlassItem() { return mItemFlags.contains(ItemFlag::IsGlassItem); }

  /**
  /**
   * Function to create the WebRenderCommands.
   * Function to create the WebRenderCommands.
   * We should check if the layer state is
   * We should check if the layer state is
@@ -3048,6 +3048,7 @@ class nsDisplayItem : public nsDisplayItemBase {
    DisableSubpixelAA,
    DisableSubpixelAA,
    ForceNotVisible,
    ForceNotVisible,
    PaintRectValid,
    PaintRectValid,
    IsGlassItem,
#ifdef MOZ_DUMP_PAINTING
#ifdef MOZ_DUMP_PAINTING
    // True if this frame has been painted.
    // True if this frame has been painted.
    Painted,
    Painted,