Commit 597b2a11 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

[SPv175+] Optimize chunk rasterization on clip change

- When possible, detect chunk_to_layer_clip change;
- When possible, issue incremental raster invalidation on clip change.

Bug: 771643
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: I8cea00f3c3ebcd035eae9bfcf29971a7a02a96df
Reviewed-on: https://chromium-review.googlesource.com/753540
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarTien-Ren Chen <trchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#517912}
parent e349345e
{
"layers": [
{
"name": "LayoutView #document",
"bounds": [800, 600],
"contentsOpaque": true,
"backgroundColor": "#FFFFFF"
},
{
"name": "LayoutBlockFlow DIV class='composited-child'",
"bounds": [100, 100],
"contentsOpaque": true,
"backfaceVisibility": "hidden",
"backgroundColor": "#008000"
},
{
"name": "Ancestor Clipping Layer",
"position": [0, 200],
"bounds": [200, 200],
"drawsContent": false
},
{
"name": "LayoutBlockFlow DIV class='composited-child'",
"position": [0, 200],
"bounds": [100, 100],
"contentsOpaque": true,
"backfaceVisibility": "hidden",
"backgroundColor": "#008000"
},
{
"name": "LayoutBlockFlow (relative positioned) DIV class='composited-child overflow-child'",
"position": [150, 150],
"bounds": [100, 100],
"contentsOpaque": true,
"backfaceVisibility": "hidden",
"backgroundColor": "#008000"
},
{
"name": "Ancestor Clipping Layer",
"position": [0, 200],
"bounds": [200, 200],
"drawsContent": false
},
{
"name": "LayoutBlockFlow (relative positioned) DIV class='composited-child overflow-child'",
"position": [150, 350],
"bounds": [100, 100],
"contentsOpaque": true,
"backfaceVisibility": "hidden",
"backgroundColor": "#008000"
}
],
"objectPaintInvalidations": [
{
"object": "LayoutBlockFlow DIV id='overflow1'",
"reason": "style change"
},
{
"object": "LayoutBlockFlow DIV id='overflow2'",
"reason": "style change"
}
]
}
......@@ -8,33 +8,18 @@
"paintInvalidations": [
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 8, 105, 112],
"reason": "paint property change"
"rect": [8, 58, 105, 62],
"reason": "incremental"
},
{
"object": "LayoutTextControl INPUT id='target'",
"rect": [8, 8, 105, 112],
"reason": "paint property change"
"rect": [8, 58, 105, 62],
"reason": "incremental"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 8, 105, 50],
"reason": "paint property change"
},
{
"object": "LayoutTextControl INPUT id='target'",
"rect": [8, 8, 105, 50],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [10, 8, 1, 107],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [10, 8, 1, 50],
"reason": "paint property change"
"rect": [10, 58, 1, 57],
"reason": "incremental"
}
]
}
......
......@@ -8,13 +8,13 @@
"paintInvalidations": [
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 8, 300, 300],
"reason": "paint property change"
"rect": [8, 8, 300, 200],
"reason": "subtree"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 8, 300, 200],
"reason": "paint property change"
"rect": [8, 208, 300, 100],
"reason": "incremental"
}
]
}
......
......@@ -7,14 +7,14 @@
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutBlockFlow DIV",
"object": "LayoutBlockFlow DIV id='s'",
"rect": [8, 156, 108, 108],
"reason": "paint property change"
"reason": "geometry"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 156, 108, 56],
"reason": "paint property change"
"rect": [8, 212, 108, 52],
"reason": "incremental"
}
]
}
......
......@@ -7,14 +7,24 @@
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutBlockFlow DIV",
"object": "InlineTextBox 'x'",
"rect": [8, 220, 100, 100],
"reason": "paint property change"
"reason": "geometry"
},
{
"object": "InlineTextBox 'x'",
"rect": [8, 220, 100, 80],
"reason": "geometry"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 300, 100, 20],
"reason": "incremental"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 200, 100, 100],
"reason": "paint property change"
"rect": [8, 200, 100, 20],
"reason": "incremental"
}
]
}
......
......@@ -14,7 +14,7 @@
{
"object": "LayoutBlockFlow HTML",
"rect": [8, 300, 60, 22],
"reason": "paint property change"
"reason": "incremental"
},
{
"object": "LayoutView #document",
......
......@@ -12,14 +12,14 @@
"reason": "geometry"
},
{
"object": "LayoutSVGRoot svg",
"object": "LayoutSVGRect rect id='targetRect'",
"rect": [9, 73, 400, 400],
"reason": "paint property change"
"reason": "geometry"
},
{
"object": "LayoutSVGRoot svg",
"rect": [9, 73, 100, 400],
"reason": "paint property change"
"rect": [109, 73, 300, 400],
"reason": "incremental"
}
]
}
......
......@@ -12,14 +12,34 @@
"reason": "geometry"
},
{
"object": "LayoutSVGRoot svg",
"object": "LayoutSVGEllipse circle",
"rect": [47, 111, 324, 324],
"reason": "paint property change"
"reason": "SVG resource change"
},
{
"object": "LayoutSVGRoot svg",
"rect": [47, 392, 324, 43],
"reason": "incremental"
},
{
"object": "LayoutSVGRoot svg",
"rect": [47, 111, 324, 43],
"reason": "incremental"
},
{
"object": "LayoutSVGRoot svg",
"rect": [110, 154, 261, 238],
"reason": "incremental"
},
{
"object": "LayoutSVGEllipse circle",
"rect": [8, 154, 170, 238],
"reason": "SVG resource change"
},
{
"object": "LayoutSVGRoot svg",
"rect": [8, 154, 102, 238],
"reason": "paint property change"
"rect": [8, 154, 39, 238],
"reason": "incremental"
}
]
}
......
......@@ -12,14 +12,14 @@
"reason": "geometry"
},
{
"object": "LayoutSVGRoot svg",
"object": "LayoutSVGImage image",
"rect": [9, 73, 400, 400],
"reason": "paint property change"
"reason": "image"
},
{
"object": "LayoutSVGRoot svg",
"rect": [9, 73, 100, 400],
"reason": "paint property change"
"rect": [109, 73, 300, 400],
"reason": "incremental"
}
]
}
......
......@@ -19,16 +19,16 @@
{
"object": "LayoutSVGRect rect id='targetRect1'",
"rect": [9, 73, 200, 200],
"reason": "paint property change"
"reason": "geometry"
},
{
"object": "LayoutSVGContainer use",
"rect": [59, 273, 50, 200],
"reason": "paint property change"
"object": "LayoutSVGRect rect id='targetRect1'",
"rect": [59, 73, 150, 200],
"reason": "incremental"
},
{
"object": "LayoutSVGRect rect id='targetRect1'",
"rect": [9, 73, 50, 200],
"object": "LayoutSVGContainer use",
"rect": [59, 273, 50, 200],
"reason": "paint property change"
}
]
......
......@@ -162,11 +162,6 @@ CASE 4, overlap1 gets removed:
"position": [300, 300],
"bounds": [100, 100],
"paintInvalidations": [
{
"object": "LayoutBlockFlow (positioned) DIV id='C' class='overlap3'",
"rect": [160, 160, 100, 100],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow (positioned) DIV id='A' class='overlap1'",
"rect": [0, 0, 100, 100],
......
......@@ -8,33 +8,18 @@
"paintInvalidations": [
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 8, 105, 112],
"reason": "paint property change"
"rect": [8, 58, 105, 62],
"reason": "incremental"
},
{
"object": "LayoutTextControl INPUT id='target'",
"rect": [8, 8, 105, 112],
"reason": "paint property change"
"rect": [8, 58, 105, 62],
"reason": "incremental"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 8, 105, 50],
"reason": "paint property change"
},
{
"object": "LayoutTextControl INPUT id='target'",
"rect": [8, 8, 105, 50],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [10, 8, 1, 107],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [10, 8, 1, 50],
"reason": "paint property change"
"rect": [10, 58, 1, 57],
"reason": "incremental"
}
]
}
......
......@@ -7,14 +7,9 @@
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutBlockFlow DIV",
"object": "LayoutBlockFlow DIV id='content'",
"rect": [8, 120, 100, 300],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 120, 100, 100],
"reason": "paint property change"
"reason": "style change"
}
]
}
......
......@@ -8,13 +8,13 @@
"paintInvalidations": [
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 8, 300, 300],
"reason": "paint property change"
"rect": [8, 8, 300, 200],
"reason": "subtree"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 8, 300, 200],
"reason": "paint property change"
"rect": [8, 208, 300, 100],
"reason": "incremental"
}
]
}
......
......@@ -23,9 +23,14 @@
"bounds": [300, 654],
"paintInvalidations": [
{
"object": "LayoutBlockFlow HTML",
"object": "InlineTextBox 'test1'",
"rect": [8, 508, 29, 19],
"reason": "paint property change"
"reason": "appeared"
},
{
"object": "InlineTextBox 'test1'",
"rect": [8, 508, 29, 19],
"reason": "disappeared"
},
{
"object": "LayoutView #document",
......
......@@ -7,14 +7,14 @@
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutBlockFlow DIV",
"object": "LayoutBlockFlow DIV id='s'",
"rect": [8, 156, 108, 108],
"reason": "paint property change"
"reason": "geometry"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 156, 108, 56],
"reason": "paint property change"
"rect": [8, 212, 108, 52],
"reason": "incremental"
}
]
}
......
......@@ -7,14 +7,24 @@
"backgroundColor": "#FFFFFF",
"paintInvalidations": [
{
"object": "LayoutBlockFlow DIV",
"object": "InlineTextBox 'x'",
"rect": [8, 220, 100, 100],
"reason": "paint property change"
"reason": "geometry"
},
{
"object": "InlineTextBox 'x'",
"rect": [8, 220, 100, 80],
"reason": "geometry"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 300, 100, 20],
"reason": "incremental"
},
{
"object": "LayoutBlockFlow DIV",
"rect": [8, 200, 100, 100],
"reason": "paint property change"
"rect": [8, 200, 100, 20],
"reason": "incremental"
}
]
}
......
......@@ -9,7 +9,7 @@
{
"object": "LayoutBlockFlow (positioned) DIV class='absolute green reflected'",
"rect": [250, 280, 100, 100],
"reason": "paint property change"
"reason": "chunk reordered"
},
{
"object": "LayoutBlockFlow (positioned) DIV id='hideMe' class='absolute red'",
......
......@@ -14,7 +14,7 @@
{
"object": "LayoutBlockFlow HTML",
"rect": [8, 300, 60, 22],
"reason": "paint property change"
"reason": "incremental"
},
{
"object": "LayoutView #document",
......
......@@ -8,23 +8,13 @@
"paintInvalidations": [
{
"object": "LayoutBlockFlow DIV id='target'",
"rect": [8, 8, 100, 200],
"reason": "paint property change"
"rect": [8, 108, 100, 100],
"reason": "incremental"
},
{
"object": "LayoutBlockFlow DIV id='target'",
"rect": [8, 8, 100, 200],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow DIV id='target'",
"rect": [8, 8, 100, 100],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow DIV id='target'",
"rect": [8, 8, 100, 100],
"reason": "paint property change"
"rect": [8, 108, 100, 100],
"reason": "incremental"
}
]
}
......
......@@ -12,14 +12,14 @@
"reason": "geometry"
},
{
"object": "LayoutSVGRoot svg",
"object": "LayoutSVGRect rect id='targetRect'",
"rect": [9, 73, 400, 400],
"reason": "paint property change"
"reason": "geometry"
},
{
"object": "LayoutSVGRoot svg",
"rect": [9, 73, 100, 400],
"reason": "paint property change"
"rect": [109, 73, 300, 400],
"reason": "incremental"
}
]
}
......
......@@ -12,14 +12,34 @@
"reason": "geometry"
},
{
"object": "LayoutSVGRoot svg",
"object": "LayoutSVGEllipse circle",
"rect": [47, 111, 324, 324],
"reason": "paint property change"
"reason": "SVG resource change"
},
{
"object": "LayoutSVGRoot svg",
"rect": [47, 392, 324, 43],
"reason": "incremental"
},
{
"object": "LayoutSVGRoot svg",
"rect": [47, 111, 324, 43],
"reason": "incremental"
},
{
"object": "LayoutSVGRoot svg",
"rect": [110, 154, 261, 238],
"reason": "incremental"
},
{
"object": "LayoutSVGEllipse circle",
"rect": [8, 154, 170, 238],
"reason": "SVG resource change"
},
{
"object": "LayoutSVGRoot svg",
"rect": [8, 154, 102, 238],
"reason": "paint property change"
"rect": [8, 154, 39, 238],
"reason": "incremental"
}
]
}
......
......@@ -12,14 +12,14 @@
"reason": "geometry"
},
{
"object": "LayoutSVGRoot svg",
"object": "LayoutSVGImage image",
"rect": [9, 73, 400, 400],
"reason": "paint property change"
"reason": "image"
},
{
"object": "LayoutSVGRoot svg",
"rect": [9, 73, 100, 400],
"reason": "paint property change"
"rect": [109, 73, 300, 400],
"reason": "incremental"
}
]
}
......
......@@ -19,16 +19,16 @@
{
"object": "LayoutSVGRect rect id='targetRect1'",
"rect": [9, 73, 200, 200],
"reason": "paint property change"
"reason": "geometry"
},
{
"object": "LayoutSVGContainer use",
"rect": [59, 273, 50, 200],
"reason": "paint property change"
"object": "LayoutSVGRect rect id='targetRect1'",
"rect": [59, 73, 150, 200],
"reason": "incremental"
},
{
"object": "LayoutSVGRect rect id='targetRect1'",
"rect": [9, 73, 50, 200],
"object": "LayoutSVGContainer use",
"rect": [59, 273, 50, 200],
"reason": "paint property change"
}
]
......
......@@ -13,10 +13,20 @@
"backfaceVisibility": "hidden",
"backgroundColor": "#FFFF00",
"paintInvalidations": [
{
"object": "LayoutBlockFlow (positioned) DIV id='target'",
"rect": [0, 0, 402, 542],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow (positioned) DIV id='target'",
"rect": [0, 0, 200, 200],
"reason": "full"
},
{
"object": "LayoutBlockFlow (positioned) DIV id='target'",
"rect": [0, 0, 200, 200],
"reason": "paint property change"
}
]
},
......
......@@ -26,16 +26,6 @@
"position": [8, 8],
"bounds": [700, 525],
"paintInvalidations": [
{
"object": "LayoutFlexibleBox (relative positioned) DIV",
"rect": [0, 493, 700, 32],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow (positioned) DIV",
"rect": [108, 508, 404, 2],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow (positioned) DIV",
"rect": [580, 508, 70, 2],
......@@ -44,17 +34,17 @@
{
"object": "LayoutBlockFlow (positioned) DIV id='thumb'",
"rect": [632, 493, 36, 32],
"reason": "paint property change"
"reason": "full"
},
{
"object": "LayoutBlockFlow (positioned) DIV id='thumb'",
"rect": [562, 493, 36, 32],
"reason": "paint property change"
"reason": "full"
},
{
"object": "LayoutBlockFlow (positioned) DIV id='thumb'",
"rect": [90, 493, 36, 32],
"reason": "paint property change"
"object": "LayoutButton INPUT class='muted'",
"rect": [530, 493, 32, 32],
"reason": "full"
}
]
}
......
......@@ -26,35 +26,25 @@
"position": [8, 8],
"bounds": [700, 525],
"paintInvalidations": [
{
"object": "LayoutFlexibleBox (relative positioned) DIV",
"rect": [0, 493, 700, 32],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow (positioned) DIV",
"rect": [108, 508, 404, 2],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow (positioned) DIV id='thumb'",
"rect": [597, 493, 36, 32],
"reason": "paint property change"
"reason": "full"
},
{
"object": "LayoutBlockFlow (positioned) DIV id='thumb'",
"rect": [562, 493, 36, 32],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow (positioned) DIV id='thumb'",
"rect": [90, 493, 36, 32],
"reason": "paint property change"
"reason": "full"
},
{
"object": "LayoutBlockFlow (positioned) DIV",
"rect": [580, 508, 35, 2],
"reason": "appeared"
},
{
"object": "LayoutButton INPUT",
"rect": [530, 493, 32, 32],
"reason": "full"
}
]
}
......
......@@ -23,12 +23,12 @@
},
{
"object": "LayoutView #document",
"rect": [0, 0, 600, 500],
"rect": [0, 0, 600, 235],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow HTML",
"rect": [168, 8, 423, 482],
"rect": [168, 8, 423, 227],
"reason": "paint property change"
}
],
......@@ -257,17 +257,17 @@
},
{
"object": "LayoutView #document",
"rect": [0, 0, 939, 235],
"rect": [0, 0, 400, 600],
"reason": "paint property change"
},
{
"object": "LayoutBlockFlow HTML",
"rect": [10, 7, 920, 213],
"object": "LayoutView #document",
"rect": [0, 0, 400, 235],
"reason": "paint property change"
},
{
"object": "LayoutView #document",
"rect": [0, 0, 400, 600],
"object": "LayoutBlockFlow HTML",
"rect": [10, 7, 390, 213],
"reason": "paint property change"
},
{
......
......@@ -42,9 +42,7 @@ IntRect CompositedLayerRasterInvalidator::MapRectFromChunkToLayer(
// so need to subtract off the layer offset.
rect.Rect().Move(-layer_bounds_.x(), -layer_bounds_.y());
rect.Rect().Inflate(chunk.outset_for_raster_effects);
return Intersection(
EnclosingIntRect(rect.Rect()),
IntRect(0, 0, layer_bounds_.width(), layer_bounds_.height()));
return ClipByLayerBounds(EnclosingIntRect(rect.Rect()));
}
TransformationMatrix CompositedLayerRasterInvalidator::ChunkToLayerTransform(
......@@ -56,6 +54,24 @@ TransformationMatrix CompositedLayerRasterInvalidator::ChunkToLayerTransform(
return matrix;
}
// Returns the clip rect when we know it is precise (no radius, no complex
// transform, no pixel moving filter, etc.)
FloatClipRect CompositedLayerRasterInvalidator::ChunkToLayerClip(
const PaintChunk& chunk) const {
FloatClipRect clip_rect;
if (chunk.properties.property_tree_state.Effect() != layer_state_.Effect()) {
// Don't bother GeometryMapper because we don't need the rect when it's not
// tight because of the effect nodes.
clip_rect.ClearIsTight();
} else {
clip_rect = GeometryMapper::LocalToAncestorClipRect(
chunk.properties.property_tree_state, layer_state_);
if (clip_rect.IsTight())
clip_rect.MoveBy(FloatPoint(-layer_bounds_.x(), -layer_bounds_.y()));
}
return clip_rect;
}
size_t CompositedLayerRasterInvalidator::MatchNewChunkToOldChunk(
const PaintChunk& new_chunk,
size_t old_index) {
......@@ -70,32 +86,50 @@ size_t CompositedLayerRasterInvalidator::MatchNewChunkToOldChunk(
return kNotFound;
}
bool CompositedLayerRasterInvalidator::ChunkPropertiesChanged(
PaintInvalidationReason
CompositedLayerRasterInvalidator::ChunkPropertiesChanged(
const PaintChunkInfo& new_chunk,
const PaintChunkInfo& old_chunk) const {
if (new_chunk.properties.backface_hidden !=
old_chunk.properties.backface_hidden)
return true;
// Treat the chunk property as changed if clip or effect node is different,
// or the value of clip or effect nodes changed between the layer state and
// the the chunk state.
const auto& new_chunk_state = new_chunk.properties.property_tree_state;
const auto& old_chunk_state = old_chunk.properties.property_tree_state;
if (new_chunk_state.Clip() != old_chunk_state.Clip() ||
new_chunk_state.Clip()->Changed(*layer_state_.Clip()) ||
new_chunk_state.Effect() != old_chunk_state.Effect() ||
new_chunk_state.Effect()->Changed(*layer_state_.Effect()))
return true;
return PaintInvalidationReason::kPaintProperty;
// Special case for transform changes because we may create or delete some
// transform nodes when no raster invalidation is needed. For example, when
// a composited layer previously not transformed now gets transformed.
// Check for real accumulated transform change instead.
if (new_chunk.chunk_to_layer_transform != old_chunk.chunk_to_layer_transform)
return true;
return PaintInvalidationReason::kPaintProperty;
return false;
// Treat the chunk property as changed if the effect node pointer is
// different, or the effect node's value changed between the layer state and
// the chunk state.
const auto& new_chunk_state = new_chunk.properties.property_tree_state;
const auto& old_chunk_state = old_chunk.properties.property_tree_state;
if (new_chunk_state.Effect() != old_chunk_state.Effect() ||
new_chunk_state.Effect()->Changed(*layer_state_.Effect()))
return PaintInvalidationReason::kPaintProperty;
// Check for accumulated clip rect change, if the clip rects are tight.
if (new_chunk.chunk_to_layer_clip.IsTight() &&
old_chunk.chunk_to_layer_clip.IsTight()) {
if (new_chunk.chunk_to_layer_clip == old_chunk.chunk_to_layer_clip)
return PaintInvalidationReason::kNone;
// Ignore differences out of the current layer bounds.
if (ClipByLayerBounds(new_chunk.chunk_to_layer_clip.Rect()) ==
ClipByLayerBounds(old_chunk.chunk_to_layer_clip.Rect()))
return PaintInvalidationReason::kNone;
return PaintInvalidationReason::kIncremental;
}
// Otherwise treat the chunk property as changed if the clip node pointer is
// different, or the clip node's value changed between the layer state and the
// chunk state.
if (new_chunk_state.Clip() != old_chunk_state.Clip() ||
new_chunk_state.Clip()->Changed(*layer_state_.Clip()))
return PaintInvalidationReason::kPaintProperty;
return PaintInvalidationReason::kNone;
}
// Generates raster invalidations by checking changes (appearing, disappearing,
......@@ -120,58 +154,61 @@ void CompositedLayerRasterInvalidator::GenerateRasterInvalidations(
const auto& new_chunk_info = new_chunks_info[new_index];
if (!new_chunk.is_cacheable) {
InvalidateRasterForNewChunk(new_chunk_info,
PaintInvalidationReason::kChunkUncacheable);
FullyInvalidateNewChunk(new_chunk_info,
PaintInvalidationReason::kChunkUncacheable);
continue;
}
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);
FullyInvalidateNewChunk(new_chunk_info,
PaintInvalidationReason::kAppeared);
continue;
}
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 = ChunkPropertiesChanged(
new_chunk_info, paint_chunks_info_[matched_old_index]);
if (!properties_changed && !moved_earlier) {
// Add the raster invalidations found by PaintController within the chunk.
AddDisplayItemRasterInvalidations(new_chunk);
} else {
auto& old_chunk_info = paint_chunks_info_[matched_old_index];
// Clip the old chunk bounds by the new layer bounds.
old_chunk_info.bounds_in_layer =
ClipByLayerBounds(old_chunk_info.bounds_in_layer);
PaintInvalidationReason reason =
matched_old_index < max_matched_old_index
? PaintInvalidationReason::kChunkReordered
: ChunkPropertiesChanged(new_chunk_info, old_chunk_info);
if (IsFullPaintInvalidationReason(reason)) {
// 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_chunk_info = paint_chunks_info_[matched_old_index];
PaintInvalidationReason reason =
properties_changed ? PaintInvalidationReason::kPaintProperty
: PaintInvalidationReason::kChunkReordered;
InvalidateRasterForOldChunk(old_chunk_info, reason);
if (old_chunk_info.bounds_in_layer != new_chunk_info.bounds_in_layer)
InvalidateRasterForNewChunk(new_chunk_info, reason);
FullyInvalidateChunk(old_chunk_info, new_chunk_info, reason);
// Ignore the display item raster invalidations because we have fully
// invalidated the chunk.
} else {
if (reason == PaintInvalidationReason::kIncremental)
IncrementallyInvalidateChunk(old_chunk_info, new_chunk_info);
// Add the raster invalidations found by PaintController within the chunk.
AddDisplayItemRasterInvalidations(new_chunk);
}
old_index = matched_old_index + 1;
if (old_index == paint_chunks_info_.size())
old_index = 0;
max_matched_old_index = std::max(max_matched_old_index, matched_old_index);
}
// Invalidate remaining unmatched (disappeared or uncacheable) old chunks.
for (size_t i = 0; i < paint_chunks_info_.size(); ++i) {
if (old_chunks_matched[i])
continue;
InvalidateRasterForOldChunk(
paint_chunks_info_[i],
paint_chunks_info_[i].is_cacheable
? PaintInvalidationReason::kDisappeared
: PaintInvalidationReason::kChunkUncacheable);
FullyInvalidateOldChunk(paint_chunks_info_[i],
paint_chunks_info_[i].is_cacheable
? PaintInvalidationReason::kDisappeared
: PaintInvalidationReason::kChunkUncacheable);
}
}
......@@ -196,31 +233,53 @@ void CompositedLayerRasterInvalidator::AddDisplayItemRasterInvalidations(
}
}
void CompositedLayerRasterInvalidator::InvalidateRasterForNewChunk(
const PaintChunkInfo& info,
void CompositedLayerRasterInvalidator::IncrementallyInvalidateChunk(
const PaintChunkInfo& old_chunk,
const PaintChunkInfo& new_chunk) {
SkRegion diff(old_chunk.bounds_in_layer);
diff.op(new_chunk.bounds_in_layer, SkRegion::kXOR_Op);
for (SkRegion::Iterator it(diff); !it.done(); it.next()) {
const SkIRect& r = it.rect();
AddRasterInvalidation(IntRect(r.x(), r.y(), r.width(), r.height()),
&new_chunk.id.client,
PaintInvalidationReason::kIncremental);
}
}
void CompositedLayerRasterInvalidator::FullyInvalidateChunk(
const PaintChunkInfo& old_chunk,
const PaintChunkInfo& new_chunk,
PaintInvalidationReason reason) {
raster_invalidation_function_(info.bounds_in_layer);
FullyInvalidateOldChunk(old_chunk, reason);
if (old_chunk.bounds_in_layer != new_chunk.bounds_in_layer)
FullyInvalidateNewChunk(new_chunk, reason);
}
if (tracking_info_) {
tracking_info_->tracking.AddInvalidation(&info.id.client,
info.id.client.DebugName(),
info.bounds_in_layer, reason);
}
void CompositedLayerRasterInvalidator::FullyInvalidateNewChunk(
const PaintChunkInfo& info,
PaintInvalidationReason reason) {
AddRasterInvalidation(info.bounds_in_layer, &info.id.client, reason);
}
void CompositedLayerRasterInvalidator::InvalidateRasterForOldChunk(
void CompositedLayerRasterInvalidator::FullyInvalidateOldChunk(
const PaintChunkInfo& info,
PaintInvalidationReason reason) {
auto bounds = info.bounds_in_layer;
bounds.Intersect(
IntRect(0, 0, layer_bounds_.width(), layer_bounds_.height()));
raster_invalidation_function_(bounds);
String debug_name;
if (tracking_info_)
debug_name = tracking_info_->old_client_debug_names.at(&info.id.client);
AddRasterInvalidation(info.bounds_in_layer, &info.id.client, reason,
&debug_name);
}
void CompositedLayerRasterInvalidator::AddRasterInvalidation(
const IntRect& rect,
const DisplayItemClient* client,
PaintInvalidationReason reason,
const String* debug_name) {
raster_invalidation_function_(rect);
if (tracking_info_) {
tracking_info_->tracking.AddInvalidation(
&info.id.client,
tracking_info_->old_client_debug_names.at(&info.id.client),
info.bounds_in_layer, reason);
client, debug_name ? *debug_name : client->DebugName(), rect, reason);
}
}
......@@ -245,10 +304,9 @@ void CompositedLayerRasterInvalidator::Generate(
Vector<PaintChunkInfo> new_chunks_info;
new_chunks_info.ReserveCapacity(paint_chunks.size());
for (const auto* chunk : paint_chunks) {
auto chunk_to_layer_transform = ChunkToLayerTransform(*chunk);
new_chunks_info.push_back(
PaintChunkInfo(MapRectFromChunkToLayer(chunk->bounds, *chunk),
chunk_to_layer_transform, *chunk));
new_chunks_info.push_back(PaintChunkInfo(
MapRectFromChunkToLayer(chunk->bounds, *chunk),
ChunkToLayerTransform(*chunk), ChunkToLayerClip(*chunk), *chunk));
if (tracking_info_) {
tracking_info_->new_client_debug_names.insert(
&chunk->id.client, chunk->id.client.DebugName());
......
......@@ -5,6 +5,7 @@
#ifndef CompositedLayerRasterInvalidator_h
#define CompositedLayerRasterInvalidator_h
#include "platform/graphics/paint/FloatClipRect.h"
#include "platform/graphics/paint/PaintChunk.h"
#include "platform/graphics/paint/RasterInvalidationTracking.h"
#include "platform/wtf/HashMap.h"
......@@ -46,12 +47,16 @@ class PLATFORM_EXPORT CompositedLayerRasterInvalidator {
const gfx::Rect& LayerBounds() const { return layer_bounds_; }
private:
friend class CompositedLayerRasterInvalidatorTest;
struct PaintChunkInfo {
PaintChunkInfo(const IntRect& bounds,
const TransformationMatrix& chunk_to_layer_transform,
const FloatClipRect& chunk_to_layer_clip,
const PaintChunk& chunk)
: bounds_in_layer(bounds),
chunk_to_layer_transform(chunk_to_layer_transform),
chunk_to_layer_clip(chunk_to_layer_clip),
id(chunk.id),
is_cacheable(chunk.is_cacheable),
properties(chunk.properties) {}
......@@ -62,6 +67,7 @@ class PLATFORM_EXPORT CompositedLayerRasterInvalidator {
IntRect bounds_in_layer;
TransformationMatrix chunk_to_layer_transform;
FloatClipRect chunk_to_layer_clip;
PaintChunk::Id id;
bool is_cacheable;
PaintChunkProperties properties;
......@@ -69,18 +75,36 @@ class PLATFORM_EXPORT CompositedLayerRasterInvalidator {
IntRect MapRectFromChunkToLayer(const FloatRect&, const PaintChunk&) const;
TransformationMatrix ChunkToLayerTransform(const PaintChunk&) const;
FloatClipRect ChunkToLayerClip(const PaintChunk&) const;
void GenerateRasterInvalidations(
const Vector<const PaintChunk*>& new_chunks,
const Vector<PaintChunkInfo>& new_chunks_info);
size_t MatchNewChunkToOldChunk(const PaintChunk& new_chunk, size_t old_index);
void AddDisplayItemRasterInvalidations(const PaintChunk&);
void InvalidateRasterForNewChunk(const PaintChunkInfo&,
PaintInvalidationReason);
void InvalidateRasterForOldChunk(const PaintChunkInfo&,
PaintInvalidationReason);
bool ChunkPropertiesChanged(const PaintChunkInfo& new_chunk,
const PaintChunkInfo& old_chunk) const;
void IncrementallyInvalidateChunk(const PaintChunkInfo& old_chunk,
const PaintChunkInfo& new_chunk);
void FullyInvalidateChunk(const PaintChunkInfo& old_chunk,
const PaintChunkInfo& new_chunk,
PaintInvalidationReason);
ALWAYS_INLINE void FullyInvalidateNewChunk(const PaintChunkInfo&,
PaintInvalidationReason);
ALWAYS_INLINE void FullyInvalidateOldChunk(const PaintChunkInfo&,
PaintInvalidationReason);
ALWAYS_INLINE void AddRasterInvalidation(const IntRect&,
const DisplayItemClient*,
PaintInvalidationReason,
const String* debug_name = nullptr);
PaintInvalidationReason ChunkPropertiesChanged(
const PaintChunkInfo& new_chunk,
const PaintChunkInfo& old_chunk) const;
// Clip a rect in the layer space by the layer bounds.
template <typename Rect>
Rect ClipByLayerBounds(const Rect& r) const {
return Intersection(
r, Rect(0, 0, layer_bounds_.width(), layer_bounds_.height()));
}
RasterInvalidationFunction raster_invalidation_function_;
gfx::Rect layer_bounds_;
......
......@@ -64,42 +64,48 @@ class CompositedLayerRasterInvalidatorTest
return EnclosingIntRect(r);
}
static void ExpectDisplayItemInvalidations(
const Vector<RasterInvalidationInfo>& invalidations,
size_t index,
const PaintChunk& chunk,
const IntPoint& chunk_offset_from_layer =
-kDefaultLayerBounds.Location()) {
for (size_t i = 0; i < chunk.raster_invalidation_rects.size(); ++i) {
SCOPED_TRACE(index + i);
const auto& info = invalidations[index + i];
EXPECT_EQ(ChunkRectToLayer(chunk.raster_invalidation_rects[i],
chunk_offset_from_layer),
info.rect);
EXPECT_EQ(&chunk.id.client, info.client);
EXPECT_EQ(chunk.raster_invalidation_tracking[i].reason, info.reason);
}
}
static void ExpectChunkInvalidation(
const Vector<RasterInvalidationInfo>& invalidations,
size_t index,
const PaintChunk& chunk,
PaintInvalidationReason reason,
const IntPoint& layer_offset = -kDefaultLayerBounds.Location()) {
SCOPED_TRACE(index);
const auto& info = invalidations[index];
EXPECT_EQ(ChunkRectToLayer(chunk.bounds, layer_offset), info.rect);
EXPECT_EQ(&chunk.id.client, info.client);
EXPECT_EQ(reason, info.reason);
}
CompositedLayerRasterInvalidator::RasterInvalidationFunction
kNoopRasterInvalidation = [this](const IntRect& rect) {};
Vector<IntRect> raster_invalidations_;
};
#define EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, index, chunk) \
do { \
for (size_t i = 0; i < (chunk).raster_invalidation_rects.size(); ++i) { \
SCOPED_TRACE(index + i); \
const auto& info = (invalidations)[index + i]; \
EXPECT_EQ(ChunkRectToLayer((chunk).raster_invalidation_rects[i], \
-kDefaultLayerBounds.Location()), \
info.rect); \
EXPECT_EQ(&(chunk).id.client, info.client); \
EXPECT_EQ((chunk).raster_invalidation_tracking[i].reason, info.reason); \
} \
} while (false)
#define EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET( \
invalidations, index, chunk, expected_reason, layer_offset) \
do { \
const auto& info = (invalidations)[index]; \
EXPECT_EQ(ChunkRectToLayer((chunk).bounds, layer_offset), info.rect); \
EXPECT_EQ(&(chunk).id.client, info.client); \
EXPECT_EQ(expected_reason, info.reason); \
} while (false)
#define EXPECT_CHUNK_INVALIDATION(invalidations, index, chunk, reason) \
EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET( \
invalidations, index, chunk, reason, -kDefaultLayerBounds.Location())
#define EXPECT_INCREMENTAL_INVALIDATION(invalidations, index, chunk, \
chunk_rect) \
do { \
const auto& info = (invalidations)[index]; \
EXPECT_EQ(ChunkRectToLayer(chunk_rect, -kDefaultLayerBounds.Location()), \
info.rect); \
EXPECT_EQ(&(chunk).id.client, info.client); \
EXPECT_EQ(PaintInvalidationReason::kIncremental, info.reason); \
} while (false)
#define CHUNKS(name, ...) \
PaintChunk name##_array[] = {__VA_ARGS__}; \
Vector<const PaintChunk*> name; \
......@@ -125,11 +131,11 @@ TEST_F(CompositedLayerRasterInvalidatorTest, LayerBounds) {
// Change of layer origin causes change of chunk0's transform to layer.
const auto& invalidations = TrackedRasterInvalidations(invalidator);
ASSERT_EQ(2u, invalidations.size());
ExpectChunkInvalidation(invalidations, 0, *chunks[0],
PaintInvalidationReason::kPaintProperty);
ExpectChunkInvalidation(invalidations, 1, *chunks[0],
PaintInvalidationReason::kPaintProperty,
-new_layer_bounds.Location());
EXPECT_CHUNK_INVALIDATION(invalidations, 0, *chunks[0],
PaintInvalidationReason::kPaintProperty);
EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET(
invalidations, 1, *chunks[0], PaintInvalidationReason::kPaintProperty,
-new_layer_bounds.Location());
}
TEST_F(CompositedLayerRasterInvalidatorTest, ReorderChunks) {
......@@ -150,14 +156,14 @@ TEST_F(CompositedLayerRasterInvalidatorTest, ReorderChunks) {
// 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]);
EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, *new_chunks[0]);
EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 2, *new_chunks[1]);
// Invalidated new chunk 2's old (as chunks[1]) and new (as new_chunks[2])
// bounds.
ExpectChunkInvalidation(invalidations, 6, *chunks[1],
PaintInvalidationReason::kChunkReordered);
ExpectChunkInvalidation(invalidations, 7, *new_chunks[2],
PaintInvalidationReason::kChunkReordered);
EXPECT_CHUNK_INVALIDATION(invalidations, 6, *chunks[1],
PaintInvalidationReason::kChunkReordered);
EXPECT_CHUNK_INVALIDATION(invalidations, 7, *new_chunks[2],
PaintInvalidationReason::kChunkReordered);
}
TEST_F(CompositedLayerRasterInvalidatorTest, ReorderChunkSubsequences) {
......@@ -180,19 +186,19 @@ TEST_F(CompositedLayerRasterInvalidatorTest, ReorderChunkSubsequences) {
// 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]);
EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, *new_chunks[0]);
EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 2, *new_chunks[1]);
EXPECT_DISPLAY_ITEM_INVALIDATIONS(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);
EXPECT_CHUNK_INVALIDATION(invalidations, 9, *chunks[1],
PaintInvalidationReason::kChunkReordered);
EXPECT_CHUNK_INVALIDATION(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, 11, *new_chunks[4],
PaintInvalidationReason::kChunkReordered);
EXPECT_CHUNK_INVALIDATION(invalidations, 11, *new_chunks[4],
PaintInvalidationReason::kChunkReordered);
}
TEST_F(CompositedLayerRasterInvalidatorTest, AppearAndDisappear) {
......@@ -209,15 +215,15 @@ TEST_F(CompositedLayerRasterInvalidatorTest, AppearAndDisappear) {
DefaultPropertyTreeState());
const auto& invalidations = TrackedRasterInvalidations(invalidator);
ASSERT_EQ(6u, invalidations.size());
ExpectDisplayItemInvalidations(invalidations, 0, *new_chunks[0]);
ExpectChunkInvalidation(invalidations, 2, *new_chunks[1],
PaintInvalidationReason::kAppeared);
ExpectChunkInvalidation(invalidations, 3, *new_chunks[2],
PaintInvalidationReason::kAppeared);
ExpectChunkInvalidation(invalidations, 4, *chunks[1],
PaintInvalidationReason::kDisappeared);
ExpectChunkInvalidation(invalidations, 5, *chunks[2],
PaintInvalidationReason::kDisappeared);
EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, *new_chunks[0]);
EXPECT_CHUNK_INVALIDATION(invalidations, 2, *new_chunks[1],
PaintInvalidationReason::kAppeared);
EXPECT_CHUNK_INVALIDATION(invalidations, 3, *new_chunks[2],
PaintInvalidationReason::kAppeared);
EXPECT_CHUNK_INVALIDATION(invalidations, 4, *chunks[1],
PaintInvalidationReason::kDisappeared);
EXPECT_CHUNK_INVALIDATION(invalidations, 5, *chunks[2],
PaintInvalidationReason::kDisappeared);
}
TEST_F(CompositedLayerRasterInvalidatorTest, AppearAtEnd) {
......@@ -232,11 +238,11 @@ TEST_F(CompositedLayerRasterInvalidatorTest, AppearAtEnd) {
DefaultPropertyTreeState());
const auto& invalidations = TrackedRasterInvalidations(invalidator);
ASSERT_EQ(4u, invalidations.size());
ExpectDisplayItemInvalidations(invalidations, 0, *new_chunks[0]);
ExpectChunkInvalidation(invalidations, 2, *new_chunks[1],
PaintInvalidationReason::kAppeared);
ExpectChunkInvalidation(invalidations, 3, *new_chunks[2],
PaintInvalidationReason::kAppeared);
EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, *new_chunks[0]);
EXPECT_CHUNK_INVALIDATION(invalidations, 2, *new_chunks[1],
PaintInvalidationReason::kAppeared);
EXPECT_CHUNK_INVALIDATION(invalidations, 3, *new_chunks[2],
PaintInvalidationReason::kAppeared);
}
TEST_F(CompositedLayerRasterInvalidatorTest, UncacheableChunks) {
......@@ -253,18 +259,22 @@ TEST_F(CompositedLayerRasterInvalidatorTest, UncacheableChunks) {
DefaultPropertyTreeState());
const auto& invalidations = TrackedRasterInvalidations(invalidator);
ASSERT_EQ(7u, invalidations.size());
ExpectDisplayItemInvalidations(invalidations, 0, *new_chunks[0]);
ExpectDisplayItemInvalidations(invalidations, 2, *new_chunks[1]);
ExpectChunkInvalidation(invalidations, 5, *new_chunks[2],
PaintInvalidationReason::kChunkUncacheable);
ExpectChunkInvalidation(invalidations, 6, *chunks[1],
PaintInvalidationReason::kChunkUncacheable);
EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, *new_chunks[0]);
EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 2, *new_chunks[1]);
EXPECT_CHUNK_INVALIDATION(invalidations, 5, *new_chunks[2],
PaintInvalidationReason::kChunkUncacheable);
EXPECT_CHUNK_INVALIDATION(invalidations, 6, *chunks[1],
PaintInvalidationReason::kChunkUncacheable);
}
TEST_F(CompositedLayerRasterInvalidatorTest, ClipPropertyChange) {
// Tests the path based on ClipPaintPropertyNode::Changed().
TEST_F(CompositedLayerRasterInvalidatorTest, ClipPropertyChangeRounded) {
CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
CHUNKS(chunks, Chunk(0), Chunk(1), Chunk(2));
FloatRoundedRect clip_rect(-100000, -100000, 200000, 200000);
FloatRoundedRect::Radii radii(FloatSize(1, 2), FloatSize(2, 3),
FloatSize(3, 4), FloatSize(4, 5));
FloatRoundedRect clip_rect(FloatRect(-1000, -1000, 2000, 2000), radii);
LOG(ERROR) << "new_clip_rect: " << clip_rect.ToString();
scoped_refptr<ClipPaintPropertyNode> clip0 = ClipPaintPropertyNode::Create(
ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
clip_rect);
......@@ -279,29 +289,33 @@ TEST_F(CompositedLayerRasterInvalidatorTest, ClipPropertyChange) {
PropertyTreeState(TransformPaintPropertyNode::Root(), clip2.get(),
EffectPaintPropertyNode::Root()));
GeometryMapperClipCache::ClearCache();
invalidator.SetTracksRasterInvalidations(true);
invalidator.Generate(kDefaultLayerBounds, chunks, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
// Change both clip0 and clip2.
LOG(ERROR) << "22222222222222222222222222222222222222222222";
CHUNKS(new_chunks, Chunk(0), Chunk(1), Chunk(2));
FloatRoundedRect new_clip_rect(-200000, -200000, 400000, 400000);
FloatRoundedRect new_clip_rect(FloatRect(-2000, -2000, 4000, 4000), radii);
LOG(ERROR) << "new_clip_rect: " << new_clip_rect.ToString();
clip0->Update(clip0->Parent(), clip0->LocalTransformSpace(), new_clip_rect);
clip2->Update(clip2->Parent(), clip2->LocalTransformSpace(), new_clip_rect);
new_chunks_array[0].properties = chunks[0]->properties;
new_chunks_array[1].properties = chunks[1]->properties;
new_chunks_array[2].properties = chunks[2]->properties;
GeometryMapperTransformCache::ClearCache();
GeometryMapperClipCache::ClearCache();
invalidator.Generate(kDefaultLayerBounds, new_chunks, layer_state);
const auto& invalidations = TrackedRasterInvalidations(invalidator);
ASSERT_EQ(1u, invalidations.size());
// Property change in the layer state should not trigger raster invalidation.
// |clip2| change should trigger raster invalidation.
ExpectChunkInvalidation(invalidations, 0, *new_chunks[2],
PaintInvalidationReason::kPaintProperty);
EXPECT_CHUNK_INVALIDATION(invalidations, 0, *new_chunks[2],
PaintInvalidationReason::kPaintProperty);
invalidator.SetTracksRasterInvalidations(false);
clip2->ClearChangedToRoot();
LOG(ERROR) << "333333333333333333333333333333333333333333333";
// Change chunk1's properties to use a different property tree state.
CHUNKS(new_chunks1, Chunk(0), Chunk(1), Chunk(2));
......@@ -309,13 +323,101 @@ TEST_F(CompositedLayerRasterInvalidatorTest, ClipPropertyChange) {
new_chunks1_array[1].properties = chunks[2]->properties;
new_chunks1_array[2].properties = chunks[2]->properties;
GeometryMapperClipCache::ClearCache();
invalidator.SetTracksRasterInvalidations(true);
invalidator.Generate(kDefaultLayerBounds, new_chunks1, layer_state);
const auto& invalidations1 = TrackedRasterInvalidations(invalidator);
ASSERT_EQ(1u, invalidations1.size());
ExpectChunkInvalidation(invalidations1, 0, *new_chunks1[1],
PaintInvalidationReason::kPaintProperty);
EXPECT_CHUNK_INVALIDATION(invalidations1, 0, *new_chunks1[1],
PaintInvalidationReason::kPaintProperty);
invalidator.SetTracksRasterInvalidations(false);
}
// Tests the path detecting change of PaintChunkInfo::chunk_to_layer_clip.
TEST_F(CompositedLayerRasterInvalidatorTest, ClipPropertyChangeSimple) {
CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
CHUNKS(chunks, Chunk(0), Chunk(1));
FloatRoundedRect clip_rect(-1000, -1000, 2000, 2000);
scoped_refptr<ClipPaintPropertyNode> clip0 = ClipPaintPropertyNode::Create(
ClipPaintPropertyNode::Root(), TransformPaintPropertyNode::Root(),
clip_rect);
scoped_refptr<ClipPaintPropertyNode> clip1 = ClipPaintPropertyNode::Create(
clip0, TransformPaintPropertyNode::Root(), clip_rect);
PropertyTreeState layer_state = PropertyTreeState::Root();
chunks_array[0].properties = PaintChunkProperties(
PropertyTreeState(TransformPaintPropertyNode::Root(), clip0.get(),
EffectPaintPropertyNode::Root()));
chunks_array[0].bounds = clip_rect.Rect();
chunks_array[1].properties = PaintChunkProperties(
PropertyTreeState(TransformPaintPropertyNode::Root(), clip1.get(),
EffectPaintPropertyNode::Root()));
chunks_array[1].bounds = clip_rect.Rect();
GeometryMapperClipCache::ClearCache();
invalidator.SetTracksRasterInvalidations(true);
invalidator.Generate(kDefaultLayerBounds, chunks, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
// Change clip1 to bigger, which is still bound by clip0, resulting no actual
// visual change.
CHUNKS(new_chunks1, Chunk(0), Chunk(1));
FloatRoundedRect new_clip_rect1(-2000, -2000, 4000, 4000);
clip1->Update(clip1->Parent(), clip1->LocalTransformSpace(), new_clip_rect1);
new_chunks1_array[0].properties = chunks[0]->properties;
new_chunks1_array[0].bounds = chunks[0]->bounds;
new_chunks1_array[1].properties = chunks[1]->properties;
new_chunks1_array[1].bounds = chunks[1]->bounds;
GeometryMapperClipCache::ClearCache();
invalidator.Generate(kDefaultLayerBounds, new_chunks1, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
clip1->ClearChangedToRoot();
// Change clip1 to smaller.
CHUNKS(new_chunks2, Chunk(0), Chunk(1));
FloatRoundedRect new_clip_rect2(-500, -500, 1000, 1000);
clip1->Update(clip1->Parent(), clip1->LocalTransformSpace(), new_clip_rect2);
new_chunks2_array[0].properties = chunks[0]->properties;
new_chunks2_array[0].bounds = chunks[0]->bounds;
new_chunks2_array[1].properties = chunks[1]->properties;
new_chunks2_array[1].bounds = new_clip_rect2.Rect();
GeometryMapperClipCache::ClearCache();
invalidator.Generate(kDefaultLayerBounds, new_chunks2, layer_state);
const auto& invalidations = TrackedRasterInvalidations(invalidator);
ASSERT_EQ(4u, invalidations.size());
// |clip1| change should trigger incremental raster invalidation.
EXPECT_INCREMENTAL_INVALIDATION(invalidations, 0, *new_chunks2[1],
IntRect(-1000, -1000, 2000, 500));
EXPECT_INCREMENTAL_INVALIDATION(invalidations, 1, *new_chunks2[1],
IntRect(-1000, -500, 500, 1000));
EXPECT_INCREMENTAL_INVALIDATION(invalidations, 2, *new_chunks2[1],
IntRect(500, -500, 500, 1000));
EXPECT_INCREMENTAL_INVALIDATION(invalidations, 3, *new_chunks2[1],
IntRect(-1000, 500, 2000, 500));
invalidator.SetTracksRasterInvalidations(false);
clip1->ClearChangedToRoot();
// Change clip1 bigger at one side.
CHUNKS(new_chunks3, Chunk(0), Chunk(1));
FloatRoundedRect new_clip_rect3(-500, -500, 2000, 1000);
clip1->Update(clip1->Parent(), clip1->LocalTransformSpace(), new_clip_rect3);
new_chunks3_array[0].properties = chunks[0]->properties;
new_chunks3_array[0].bounds = chunks[0]->bounds;
new_chunks3_array[1].properties = chunks[1]->properties;
new_chunks3_array[1].bounds = new_clip_rect3.Rect();
GeometryMapperClipCache::ClearCache();
invalidator.SetTracksRasterInvalidations(true);
invalidator.Generate(kDefaultLayerBounds, new_chunks3, layer_state);
const auto& invalidations1 = TrackedRasterInvalidations(invalidator);
ASSERT_EQ(1u, invalidations1.size());
// |clip1| change should trigger incremental raster invalidation.
EXPECT_INCREMENTAL_INVALIDATION(invalidations1, 0, *new_chunks3[1],
IntRect(500, -500, 500, 1000));
invalidator.SetTracksRasterInvalidations(false);
clip1->ClearChangedToRoot();
}
TEST_F(CompositedLayerRasterInvalidatorTest, TransformPropertyChange) {
......@@ -408,12 +510,14 @@ TEST_F(CompositedLayerRasterInvalidatorTest, TransformPropertyChange) {
invalidator.Generate(kDefaultLayerBounds, new_chunks3, layer_state);
const auto& invalidations = TrackedRasterInvalidations(invalidator);
ASSERT_EQ(2u, invalidations.size());
ExpectChunkInvalidation(invalidations, 0, *new_chunks3[0],
PaintInvalidationReason::kPaintProperty,
-kDefaultLayerBounds.Location() + IntSize(10, 20));
ExpectChunkInvalidation(invalidations, 1, *new_chunks3[0],
PaintInvalidationReason::kPaintProperty,
-kDefaultLayerBounds.Location() + IntSize(30, 50));
EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET(
invalidations, 0, *new_chunks3[0],
PaintInvalidationReason::kPaintProperty,
-kDefaultLayerBounds.Location() + IntSize(10, 20));
EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET(
invalidations, 1, *new_chunks3[0],
PaintInvalidationReason::kPaintProperty,
-kDefaultLayerBounds.Location() + IntSize(30, 50));
invalidator.SetTracksRasterInvalidations(false);
}
......
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