Commit ad5901e7 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

[SPv2] Fix raster invalidation on chunk reordering

Instead of invalidating chunks that are not in sequence of the
previous chunks, now invalidate chunks which are moved before
any previously matched chunks. This is the same method used in
PaintController to invalidate reordered display items.

Bug: 771770
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: Idca6531db89a149a7280079b5ff598b77de97d0a
Reviewed-on: https://chromium-review.googlesource.com/710314Reviewed-by: default avatarTien-Ren Chen <trchen@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#509266}
parent 043b5e97
......@@ -14,7 +14,7 @@
{
"object": "LayoutBlockFlow (relative positioned) DIV",
"rect": [108, 8, 100, 100],
"reason": "chunk reordered"
"reason": "disappeared"
},
{
"object": "LayoutBlockFlow DIV",
......
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF"
},
{
"name": "LayoutBlockFlow DIV",
"bounds": [550, 550],
"backgroundColor": "#FF0000",
"paintInvalidations": [
{
"object": "LayoutBlockFlow (positioned) DIV id='chunk3'",
"rect": [400, 400, 100, 100],
"reason": "chunk reordered"
},
{
"object": "LayoutBlockFlow (positioned) DIV id='chunk2'",
"rect": [0, 0, 1, 1],
"reason": "chunk reordered"
}
],
"transform": 1
}
],
"transforms": [
{
"id": 1,
"transform": [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[8, 8, 0, 1]
]
}
]
}
......@@ -11,11 +11,6 @@
"rect": [0, 114, 302, 46],
"reason": "appeared"
},
{
"object": "InlineTextBox 'PASS '",
"rect": [0, 64, 302, 46],
"reason": "chunk reordered"
},
{
"object": "LayoutSVGRoot (positioned) svg",
"rect": [0, 14, 302, 46],
......
<!DOCTYPE html>
<div style="position:relative; width:1px; height:1px; background:orange;">
<div style="position:absolute; left:450px; top:450px; width:100px; height:100px; background:blue;"></div>
<div style="position:absolute; left:400px; top:400px; width:100px; height:100px; background:yellow;"></div>
</div>
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF"
},
{
"name": "LayoutBlockFlow DIV",
"bounds": [784, 550],
"paintInvalidations": [
{
"object": "LayoutBlockFlow (positioned) DIV id='chunk3'",
"rect": [400, 400, 100, 100],
"reason": "subtree"
},
{
"object": "LayoutBlockFlow (positioned) DIV id='chunk2'",
"rect": [0, 0, 1, 1],
"reason": "subtree"
}
],
"transform": 1
}
],
"transforms": [
{
"id": 1,
"transform": [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[8, 8, 0, 1]
]
}
],
"objectPaintInvalidations": [
{
"object": "LayoutBlockFlow (positioned) DIV id='chunk2'",
"reason": "subtree"
},
{
"object": "LayoutBlockFlow (positioned) DIV id='chunk3'",
"reason": "subtree"
}
]
}
<!DOCTYPE html>
<div style="transform:translateZ(0);">
<div id="chunk1" style="width:1px; height:1px; background:red;"></div>
<div id="chunk2" style="transform:translateX(0); position:absolute; z-index:0; left:0; top:0; width:1px; height:1px; background:orange;"></div>
<div id="chunk3" style="transform:translateX(0); position:absolute; z-index:1; left:400px; top:400px; width:100px; height:100px; background:yellow;"></div>
<div id="chunk4" style="transform:translateX(0); position:absolute; z-index:2; left:0; top:0; width:1px; height:1px; background:green;"></div>
<div id="chunk5" style="transform:translateX(0); position:absolute; z-index:3; left:450px; top:450px; width:100px; height:100px; background:blue;"></div>
</div>
<script src="../resources/text-based-repaint.js"></script>
<script>
function repaintTest() {
document.getElementById("chunk2").style.zIndex = "4";
document.getElementById("chunk3").style.zIndex = "5";
}
onload = runRepaintAndPixelTest;
</script>
......@@ -71,6 +71,7 @@ void CompositedLayerRasterInvalidator::GenerateRasterInvalidations(
Vector<bool> old_chunks_matched;
old_chunks_matched.resize(paint_chunks_info_.size());
size_t old_index = 0;
size_t max_matched_old_index = 0;
for (size_t new_index = 0; new_index < new_chunks.size(); ++new_index) {
const auto& new_chunk = *new_chunks[new_index];
const auto& new_chunk_info = new_chunks_info[new_index];
......@@ -81,28 +82,31 @@ void CompositedLayerRasterInvalidator::GenerateRasterInvalidations(
continue;
}
size_t matched = MatchNewChunkToOldChunk(new_chunk, old_index);
if (matched == kNotFound) {
size_t matched_old_index = MatchNewChunkToOldChunk(new_chunk, old_index);
if (matched_old_index == kNotFound) {
// The new chunk doesn't match any old chunk.
InvalidateRasterForNewChunk(new_chunk_info,
PaintInvalidationReason::kAppeared);
continue;
}
DCHECK(!old_chunks_matched[matched]);
old_chunks_matched[matched] = true;
DCHECK(!old_chunks_matched[matched_old_index]);
old_chunks_matched[matched_old_index] = true;
bool moved_earlier = matched_old_index < max_matched_old_index;
max_matched_old_index = std::max(max_matched_old_index, matched_old_index);
bool properties_changed =
new_chunk.properties != paint_chunks_info_[matched].properties ||
new_chunk.properties !=
paint_chunks_info_[matched_old_index].properties ||
new_chunk.properties.property_tree_state.Changed(layer_state_);
if (!properties_changed && matched == old_index) {
if (!properties_changed && !moved_earlier) {
// Add the raster invalidations found by PaintController within the chunk.
AddDisplayItemRasterInvalidations(new_chunk);
} else {
// Invalidate both old and new bounds of the chunk if the chunk's paint
// properties changed, or is moved backward and may expose area that was
// previously covered by it.
const auto& old_chunks_info = paint_chunks_info_[matched];
const auto& old_chunks_info = paint_chunks_info_[matched_old_index];
PaintInvalidationReason reason =
properties_changed ? PaintInvalidationReason::kPaintProperty
: PaintInvalidationReason::kChunkReordered;
......@@ -113,7 +117,7 @@ void CompositedLayerRasterInvalidator::GenerateRasterInvalidations(
// invalidated the chunk.
}
old_index = matched + 1;
old_index = matched_old_index + 1;
if (old_index == paint_chunks_info_.size())
old_index = 0;
}
......
......@@ -138,25 +138,57 @@ TEST_F(CompositedLayerRasterInvalidatorTest, ReorderChunks) {
// Swap chunk 1 and 2. All chunks have their own local raster invalidations.
CHUNKS(new_chunks, Chunk(0, 2), Chunk(2, 4), Chunk(1, 3));
new_chunks_array[1].bounds = FloatRect(11, 22, 33, 44);
new_chunks_array[2].bounds = FloatRect(11, 22, 33, 44);
invalidator.Generate(kDefaultLayerBounds, new_chunks,
DefaultPropertyTreeState());
const auto& invalidations = TrackedRasterInvalidations(invalidator);
ASSERT_EQ(5u, invalidations.size());
ASSERT_EQ(8u, invalidations.size());
// The first chunk should always match because otherwise we won't reuse the
// CompositedLayerRasterInvalidator (which is according to the first chunk's
// id). For matched chunk, we issue raster invalidations if any found by
// PaintController.
ExpectDisplayItemInvalidations(invalidations, 0, *new_chunks[0]);
// Invalidated new chunk 1's old (as chunks[2]) and new (as new_chunks[1])
ExpectDisplayItemInvalidations(invalidations, 2, *new_chunks[1]);
// Invalidated new chunk 2's old (as chunks[1]) and new (as new_chunks[2])
// bounds.
ExpectChunkInvalidation(invalidations, 2, *chunks[2],
ExpectChunkInvalidation(invalidations, 6, *chunks[1],
PaintInvalidationReason::kChunkReordered);
ExpectChunkInvalidation(invalidations, 3, *new_chunks[1],
ExpectChunkInvalidation(invalidations, 7, *new_chunks[2],
PaintInvalidationReason::kChunkReordered);
// Invalidated new chunk 2's new bounds. Didn't invalidate old bounds because
}
TEST_F(CompositedLayerRasterInvalidatorTest, ReorderChunkSubsequences) {
CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
CHUNKS(chunks, Chunk(0), Chunk(1), Chunk(2), Chunk(3), Chunk(4));
invalidator.SetTracksRasterInvalidations(true);
invalidator.Generate(kDefaultLayerBounds, chunks, DefaultPropertyTreeState());
EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
// Swap chunk (1,2) and (3,4). All chunks have their own local raster
// invalidations.
CHUNKS(new_chunks, Chunk(0, 2), Chunk(3, 3), Chunk(4, 4), Chunk(1, 1),
Chunk(2, 2));
new_chunks_array[3].bounds = FloatRect(11, 22, 33, 44);
invalidator.Generate(kDefaultLayerBounds, new_chunks,
DefaultPropertyTreeState());
const auto& invalidations = TrackedRasterInvalidations(invalidator);
ASSERT_EQ(12u, invalidations.size());
// The first chunk should always match because otherwise we won't reuse the
// CompositedLayerRasterInvalidator (which is according to the first chunk's
// id). For matched chunk, we issue raster invalidations if any found by
// PaintController.
ExpectDisplayItemInvalidations(invalidations, 0, *new_chunks[0]);
ExpectDisplayItemInvalidations(invalidations, 2, *new_chunks[1]);
ExpectDisplayItemInvalidations(invalidations, 5, *new_chunks[2]);
// Invalidated new chunk 3's old (as chunks[1]) and new (as new_chunks[3])
// bounds.
ExpectChunkInvalidation(invalidations, 9, *chunks[1],
PaintInvalidationReason::kChunkReordered);
ExpectChunkInvalidation(invalidations, 10, *new_chunks[3],
PaintInvalidationReason::kChunkReordered);
// Invalidated new chunk 4's new bounds. Didn't invalidate old bounds because
// it's the same as the new bounds.
ExpectChunkInvalidation(invalidations, 4, *new_chunks[2],
ExpectChunkInvalidation(invalidations, 11, *new_chunks[4],
PaintInvalidationReason::kChunkReordered);
}
......@@ -217,13 +249,12 @@ TEST_F(CompositedLayerRasterInvalidatorTest, UncacheableChunks) {
invalidator.Generate(kDefaultLayerBounds, new_chunks,
DefaultPropertyTreeState());
const auto& invalidations = TrackedRasterInvalidations(invalidator);
ASSERT_EQ(5u, invalidations.size());
ASSERT_EQ(7u, invalidations.size());
ExpectDisplayItemInvalidations(invalidations, 0, *new_chunks[0]);
ExpectChunkInvalidation(invalidations, 2, *new_chunks[1],
PaintInvalidationReason::kChunkReordered);
ExpectChunkInvalidation(invalidations, 3, *new_chunks[2],
ExpectDisplayItemInvalidations(invalidations, 2, *new_chunks[1]);
ExpectChunkInvalidation(invalidations, 5, *new_chunks[2],
PaintInvalidationReason::kChunkUncacheable);
ExpectChunkInvalidation(invalidations, 4, *chunks[1],
ExpectChunkInvalidation(invalidations, 6, *chunks[1],
PaintInvalidationReason::kChunkUncacheable);
}
......
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