Commit 582adea6 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

Handle squashed layer switching between scrolling and non-scrolling

Bug: 1084839
Change-Id: I96882277cbd4a95aff53dda5c0f6ecd37bbf954e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2212669Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#771947}
parent d845bf71
......@@ -2148,23 +2148,6 @@ void CompositedLayerMapping::VerifyNotPainting() {
}
#endif
bool CompositedLayerMapping::InvalidateSquashedLayerIfNoPrecedingEntry(
Vector<GraphicsLayerPaintInfo>& squashed_layers,
wtf_size_t index_to_clear) {
PaintLayer* layer_to_remove = squashed_layers[index_to_clear].paint_layer;
wtf_size_t previous_index = 0;
for (; previous_index < index_to_clear; ++previous_index) {
if (squashed_layers[previous_index].paint_layer == layer_to_remove)
break;
}
if (previous_index == index_to_clear &&
layer_to_remove->GroupedMapping() == this) {
Compositor()->PaintInvalidationOnCompositingChange(layer_to_remove);
return true;
}
return false;
}
bool CompositedLayerMapping::UpdateSquashingLayerAssignmentInternal(
Vector<GraphicsLayerPaintInfo>& squashed_layers,
PaintLayer& squashed_layer,
......@@ -2181,22 +2164,12 @@ bool CompositedLayerMapping::UpdateSquashingLayerAssignmentInternal(
if (paint_info.paint_layer ==
squashed_layers[next_squashed_layer_index].paint_layer)
return false;
// Must invalidate before adding the squashed layer to the mapping.
Compositor()->PaintInvalidationOnCompositingChange(&squashed_layer);
// If the layer which was previously at |nextSquashedLayerIndex| is not
// earlier in the grouped mapping, invalidate its current backing now, since
// it will move later or be removed from the squashing layer.
InvalidateSquashedLayerIfNoPrecedingEntry(squashed_layers,
next_squashed_layer_index);
squashed_layers.insert(next_squashed_layer_index, paint_info);
} else {
// Must invalidate before adding the squashed layer to the mapping.
Compositor()->PaintInvalidationOnCompositingChange(&squashed_layer);
squashed_layers.push_back(paint_info);
}
// Must invalidate before adding the squashed layer to the mapping.
Compositor()->PaintInvalidationOnCompositingChange(&squashed_layer);
squashed_layer.SetGroupedMapping(
this, PaintLayer::kInvalidateLayerAndRemoveFromMapping);
......@@ -2239,7 +2212,6 @@ void CompositedLayerMapping::RemoveLayerFromSquashingGraphicsLayer(
NOTREACHED();
}
#if DCHECK_IS_ON()
static bool LayerInSquashedLayersVector(
const Vector<GraphicsLayerPaintInfo>& squashed_layers,
const PaintLayer& layer) {
......@@ -2250,6 +2222,7 @@ static bool LayerInSquashedLayersVector(
return false;
}
#if DCHECK_IS_ON()
void CompositedLayerMapping::AssertInSquashedLayersVector(
const PaintLayer& squashed_layer) const {
auto* in = &non_scrolling_squashed_layers_;
......@@ -2261,43 +2234,44 @@ void CompositedLayerMapping::AssertInSquashedLayersVector(
}
#endif
void CompositedLayerMapping::FinishAccumulatingSquashingLayersInternal(
static void RemoveExtraSquashedLayers(
Vector<GraphicsLayerPaintInfo>& squashed_layers,
wtf_size_t new_squashed_layer_count,
wtf_size_t new_count,
Vector<PaintLayer*>& layers_needing_paint_invalidation) {
if (new_squashed_layer_count < squashed_layers.size()) {
// Any additional squashed Layers in the array no longer belong here, but
// they might have been added already at an earlier index. Clear pointers on
// those that do not appear in the valid set before removing all the extra
// entries.
for (wtf_size_t i = new_squashed_layer_count; i < squashed_layers.size();
++i) {
if (InvalidateSquashedLayerIfNoPrecedingEntry(squashed_layers, i)) {
squashed_layers[i].paint_layer->SetGroupedMapping(
nullptr, PaintLayer::kDoNotInvalidateLayerAndRemoveFromMapping);
squashed_layers[i].paint_layer->SetLostGroupedMapping(true);
}
layers_needing_paint_invalidation.push_back(
squashed_layers[i].paint_layer);
}
squashed_layers.EraseAt(new_squashed_layer_count,
squashed_layers.size() - new_squashed_layer_count);
}
DCHECK_GE(squashed_layers.size(), new_count);
if (squashed_layers.size() == new_count)
return;
for (auto i = new_count; i < squashed_layers.size(); i++)
layers_needing_paint_invalidation.push_back(squashed_layers[i].paint_layer);
squashed_layers.Shrink(new_count);
}
void CompositedLayerMapping::FinishAccumulatingSquashingLayers(
wtf_size_t new_squashed_layer_in_non_scrolling_squashing_layer_count,
wtf_size_t new_non_scrolling_squashed_layer_count,
wtf_size_t new_squashed_layer_in_scrolling_contents_count,
Vector<PaintLayer*>& layers_needing_paint_invalidation) {
FinishAccumulatingSquashingLayersInternal(
non_scrolling_squashed_layers_,
new_squashed_layer_in_non_scrolling_squashing_layer_count,
layers_needing_paint_invalidation);
FinishAccumulatingSquashingLayersInternal(
squashed_layers_in_scrolling_contents_,
new_squashed_layer_in_scrolling_contents_count,
layers_needing_paint_invalidation);
wtf_size_t first_removed_layer = layers_needing_paint_invalidation.size();
RemoveExtraSquashedLayers(non_scrolling_squashed_layers_,
new_non_scrolling_squashed_layer_count,
layers_needing_paint_invalidation);
RemoveExtraSquashedLayers(squashed_layers_in_scrolling_contents_,
new_squashed_layer_in_scrolling_contents_count,
layers_needing_paint_invalidation);
for (auto i = first_removed_layer;
i < layers_needing_paint_invalidation.size(); i++) {
PaintLayer* layer = layers_needing_paint_invalidation[i];
// Deal with layers that are no longer squashed. Need to check both vectors
// to exclude the layers that are still squashed. A layer may change from
// scrolling to non-scrolling or vice versa and still be squashed.
if (!LayerInSquashedLayersVector(non_scrolling_squashed_layers_, *layer) &&
!LayerInSquashedLayersVector(squashed_layers_in_scrolling_contents_,
*layer)) {
Compositor()->PaintInvalidationOnCompositingChange(layer);
layer->SetGroupedMapping(
nullptr, PaintLayer::kDoNotInvalidateLayerAndRemoveFromMapping);
layer->SetLostGroupedMapping(true);
}
}
}
String CompositedLayerMapping::DebugName(
......
......@@ -396,16 +396,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
const Vector<GraphicsLayerPaintInfo>& layers,
GraphicsLayerPaintInfo&);
// Clear the groupedMapping entry on the layer at the given index, only if
// that layer does not appear earlier in the set of layers for this object.
bool InvalidateSquashedLayerIfNoPrecedingEntry(
Vector<GraphicsLayerPaintInfo>& squashed_layers,
wtf_size_t layer_to_clear);
void FinishAccumulatingSquashingLayersInternal(
Vector<GraphicsLayerPaintInfo>& squashed_layers,
wtf_size_t new_squashed_layer_count,
Vector<PaintLayer*>& layers_needing_paint_invalidation);
bool UpdateSquashingLayerAssignmentInternal(
Vector<GraphicsLayerPaintInfo>& squashed_layers,
PaintLayer& squashed_layer,
......
......@@ -56,17 +56,29 @@ class CompositedLayerMappingTest : public RenderingTest {
return graphics_layer->previous_interest_rect_;
}
const GraphicsLayerPaintInfo* GetSquashedLayerInScrollingContents(
const CompositedLayerMapping& mapping,
static const GraphicsLayerPaintInfo* GetSquashedLayer(
const Vector<GraphicsLayerPaintInfo>& squashed_layers,
const PaintLayer& layer) {
for (const auto& squashed_layer :
mapping.squashed_layers_in_scrolling_contents_) {
for (const auto& squashed_layer : squashed_layers) {
if (squashed_layer.paint_layer == &layer)
return &squashed_layer;
}
return nullptr;
}
const GraphicsLayerPaintInfo* GetNonScrollingSquashedLayer(
const CompositedLayerMapping& mapping,
const PaintLayer& layer) {
return GetSquashedLayer(mapping.non_scrolling_squashed_layers_, layer);
}
const GraphicsLayerPaintInfo* GetSquashedLayerInScrollingContents(
const CompositedLayerMapping& mapping,
const PaintLayer& layer) {
return GetSquashedLayer(mapping.squashed_layers_in_scrolling_contents_,
layer);
}
private:
void SetUp() override {
EnableCompositing();
......@@ -1935,4 +1947,53 @@ TEST_F(CompositedLayerMappingTest, SquashIntoScrollingContents) {
EXPECT_TRUE(target2->HasCompositedLayerMapping());
}
TEST_F(CompositedLayerMappingTest,
SwitchSquashingBetweenScrollingAndNonScrolling) {
GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
true);
SetBodyInnerHTML(R"HTML(
<style>.scroll { overflow: scroll; }</style>
<div id="container"
style="backface-visibility: hidden; width: 100px; height: 100px">
<div id="squashed"
style="z-index: 1; position: relative; width: 10px; height: 10px"></div>
<div id="filler" style="height: 300px"></div>
</div>
)HTML");
auto* container_element = GetDocument().getElementById("container");
auto* container = container_element->GetLayoutBox()->Layer();
auto* squashed = ToLayoutBox(GetLayoutObjectByElementId("squashed"))->Layer();
auto* mapping = container->GetCompositedLayerMapping();
ASSERT_TRUE(mapping);
EXPECT_EQ(mapping, squashed->GroupedMapping());
EXPECT_EQ(mapping->NonScrollingSquashingLayer(),
squashed->GraphicsLayerBacking());
EXPECT_EQ(mapping->NonScrollingSquashingLayer(),
mapping->SquashingLayer(*squashed));
EXPECT_TRUE(GetNonScrollingSquashedLayer(*mapping, *squashed));
EXPECT_FALSE(GetSquashedLayerInScrollingContents(*mapping, *squashed));
container_element->setAttribute(html_names::kClassAttr, "scroll");
UpdateAllLifecyclePhasesForTest();
ASSERT_EQ(mapping, container->GetCompositedLayerMapping());
EXPECT_EQ(mapping, squashed->GroupedMapping());
EXPECT_EQ(mapping->ScrollingContentsLayer(),
squashed->GraphicsLayerBacking());
EXPECT_EQ(mapping->ScrollingContentsLayer(),
mapping->SquashingLayer(*squashed));
EXPECT_FALSE(GetNonScrollingSquashedLayer(*mapping, *squashed));
EXPECT_TRUE(GetSquashedLayerInScrollingContents(*mapping, *squashed));
container_element->setAttribute(html_names::kClassAttr, "");
UpdateAllLifecyclePhasesForTest();
ASSERT_EQ(mapping, container->GetCompositedLayerMapping());
EXPECT_EQ(mapping->NonScrollingSquashingLayer(),
squashed->GraphicsLayerBacking());
EXPECT_EQ(mapping->NonScrollingSquashingLayer(),
mapping->SquashingLayer(*squashed));
EXPECT_TRUE(GetNonScrollingSquashedLayer(*mapping, *squashed));
EXPECT_FALSE(GetSquashedLayerInScrollingContents(*mapping, *squashed));
}
} // namespace blink
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