Commit a3c8efc9 authored by Steve Kobes's avatar Steve Kobes Committed by Commit Bot

Update sticky layers in tree order after scroll.

The position of a nested sticky layer depends on the position of its
sticky ancestor.  If the ancestor hasn't been positioned, we get the
wrong offset from StickyPositionScrollingConstraints.

PLSA's iteration over the StickyConstraintsMap has unspecified ordering.
Instead, use the recursive tree walk of UpdateLayerPositionRecursive
(but preserve the optimization of skipping non-sticky layers when the
root PLSA is scrolled).

Bug: 821216
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: I61ca51a69fdbb857d88713afcdd92f8615930cd1
Reviewed-on: https://chromium-review.googlesource.com/963516Reviewed-by: default avatarStefan Zager <szager@chromium.org>
Commit-Queue: Steve Kobes <skobes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#543841}
parent ccc9d24f
......@@ -3388,8 +3388,3 @@ crbug.com/819778 [ Linux ] external/wpt/css/cssom-view/interfaces.html [ Pass Ti
# Sheriff 2018-03-08
crbug.com/731518 [ Win Linux Mac ] webaudio/DynamicsCompressor/dynamicscompressor-clear-internal-state.html [ Failure Pass ]
# LayoutGeometryMap DCHECK with nested sticky and scroll offset
crbug.com/821216 compositing/overflow/mixed-composited-nested-sticky.html [ Crash Pass ]
crbug.com/821216 virtual/prefer_compositing_to_lcd_text/compositing/overflow/mixed-composited-nested-sticky.html [ Crash Pass ]
crbug.com/821216 virtual/disable-spv175/compositing/overflow/mixed-composited-nested-sticky.html [ Crash Pass ]
......@@ -312,11 +312,26 @@ void PaintLayer::UpdateLayerPositionsAfterLayout() {
}
}
void PaintLayer::UpdateLayerPositionRecursive() {
void PaintLayer::UpdateLayerPositionRecursive(
UpdateLayerPositionBehavior behavior) {
switch (behavior) {
case AllLayers:
UpdateLayerPosition();
break;
case OnlyStickyLayers:
if (GetLayoutObject().Style()->HasStickyConstrainedPosition())
UpdateLayerPosition();
if (PaintLayerScrollableArea* scroller = GetScrollableArea()) {
if (!scroller->HasStickyDescendants())
return;
}
break;
default:
NOTREACHED();
}
for (PaintLayer* child = FirstChild(); child; child = child->NextSibling())
child->UpdateLayerPositionRecursive();
child->UpdateLayerPositionRecursive(behavior);
}
void PaintLayer::UpdateHasSelfPaintingLayerDescendant() const {
......@@ -398,16 +413,17 @@ bool PaintLayer::ScrollsWithRespectTo(const PaintLayer* other) const {
}
void PaintLayer::UpdateLayerPositionsAfterOverflowScroll() {
// The root PaintLayer (i.e. the LayoutView) is special, in that scroll offset
// is not included in clip rects. Therefore, we do not need to clear them
// when that PaintLayer is scrolled. We also don't need to update layer
// positions, because they also do not depend on the root's scroll offset.
if (IsRootLayer()) {
GetScrollableArea()->UpdateLayerPositionForStickyDescendants();
} else {
ClearClipRects();
UpdateLayerPositionRecursive();
// The root PaintLayer (i.e. the LayoutView) is special, in that scroll
// offset is not included in clip rects. Therefore, we do not need to clear
// them when that PaintLayer is scrolled. We also don't need to update layer
// positions, because they also do not depend on the root's scroll offset.
if (GetScrollableArea()->HasStickyDescendants())
UpdateLayerPositionRecursive(OnlyStickyLayers);
return;
}
ClearClipRects();
UpdateLayerPositionRecursive(AllLayers);
}
void PaintLayer::UpdateTransformationMatrix() {
......
......@@ -1028,7 +1028,8 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
void DirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
void UpdateLayerPositionRecursive();
enum UpdateLayerPositionBehavior { AllLayers, OnlyStickyLayers };
void UpdateLayerPositionRecursive(UpdateLayerPositionBehavior = AllLayers);
void SetNextSibling(PaintLayer* next) { next_ = next; }
void SetPreviousSibling(PaintLayer* prev) { previous_ = prev; }
......
......@@ -1860,6 +1860,12 @@ void PaintLayerScrollableArea::InvalidateStickyConstraintsFor(
}
}
bool PaintLayerScrollableArea::HasStickyDescendants() const {
if (const PaintLayerScrollableAreaRareData* d = RareData())
return !d->sticky_constraints_map_.IsEmpty();
return false;
}
bool PaintLayerScrollableArea::HasNonCompositedStickyDescendants() const {
if (const PaintLayerScrollableAreaRareData* d = RareData()) {
for (const PaintLayer* sticky_layer : d->sticky_constraints_map_.Keys()) {
......@@ -1879,13 +1885,6 @@ void PaintLayerScrollableArea::InvalidatePaintForStickyDescendants() {
}
}
void PaintLayerScrollableArea::UpdateLayerPositionForStickyDescendants() {
if (PaintLayerScrollableAreaRareData* d = RareData()) {
for (PaintLayer* sticky_layer : d->sticky_constraints_map_.Keys())
sticky_layer->UpdateLayerPosition();
}
}
IntSize PaintLayerScrollableArea::OffsetFromResizeCorner(
const IntPoint& absolute_point) const {
// Currently the resize corner is either the bottom right corner or the bottom
......
......@@ -486,7 +486,7 @@ class CORE_EXPORT PaintLayerScrollableArea final
void InvalidateStickyConstraintsFor(PaintLayer*,
bool needs_compositing_update = true);
void InvalidatePaintForStickyDescendants();
void UpdateLayerPositionForStickyDescendants();
bool HasStickyDescendants() const;
bool HasNonCompositedStickyDescendants() const;
uint32_t GetNonCompositedMainThreadScrollingReasons() {
return non_composited_main_thread_scrolling_reasons_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment