Commit d780342d authored by Philip Rogers's avatar Philip Rogers Committed by Chromium LUCI CQ

Preserve compositor damage from decomposited transforms

Transform nodes store a changed field that is used to cause damage in
the compositor (see: PaintArtifactCompositor::PropertyTreeStateChanged).
We need to ensure changed state is not lost when decompositing (see:
PaintArtifactCompositor::DecompositeTransforms). This patch takes a
simple approach of recording the changes of decomposited transform nodes
on PendingLayers, and using that to cause damage. This fixes a bug where
a change on a decomposited transform node failed to cause damage.

http://crrev.com/c/2626192 explored an approach of not decompositing
nodes with changes but that leads to unnecessary additional layers.

Bug: 1164513
Change-Id: I9c6d68f748772e9c2a86158e62bc0c7db3e8733f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2627943
Commit-Queue: Philip Rogers <pdr@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Auto-Submit: Philip Rogers <pdr@chromium.org>
Reviewed-by: default avatarXianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843292}
parent 7b4bda20
...@@ -1773,4 +1773,30 @@ TEST_P(CompositingSimTest, VisibleFrameRootLayers) { ...@@ -1773,4 +1773,30 @@ TEST_P(CompositingSimTest, VisibleFrameRootLayers) {
EXPECT_FALSE(iframe_transform_node->visible_frame_element_id); EXPECT_FALSE(iframe_transform_node->visible_frame_element_id);
} }
TEST_P(CompositingSimTest, DecompositedTransformWithChange) {
InitializeWithHTML(R"HTML(
<style>
svg { overflow: hidden; }
.initial { transform: rotate3d(0,0,1,10deg); }
.changed { transform: rotate3d(0,0,1,0deg); }
</style>
<div style='will-change: transform;'>
<svg id='svg' xmlns='http://www.w3.org/2000/svg' class='initial'>
<line x1='50%' x2='50%' y1='0' y2='100%' stroke='blue'/>
<line y1='50%' y2='50%' x1='0' x2='100%' stroke='blue'/>
</svg>
</div>
)HTML");
Compositor().BeginFrame();
auto* svg_element_layer = CcLayerByDOMElementId("svg");
EXPECT_FALSE(svg_element_layer->subtree_property_changed());
auto* svg_element = GetElementById("svg");
svg_element->setAttribute(html_names::kClassAttr, "changed");
UpdateAllLifecyclePhases();
EXPECT_TRUE(svg_element_layer->subtree_property_changed());
}
} // namespace blink } // namespace blink
...@@ -316,13 +316,17 @@ bool PaintArtifactCompositor::HasComposited( ...@@ -316,13 +316,17 @@ bool PaintArtifactCompositor::HasComposited(
element_id); element_id);
} }
bool PaintArtifactCompositor::PropertyTreeStateChanged( bool PaintArtifactCompositor::PendingLayer::PropertyTreeStateChanged() const {
const PropertyTreeState& state) const {
const auto& root = PropertyTreeState::Root();
auto change = PaintPropertyChangeType::kChangedOnlyNonRerasterValues; auto change = PaintPropertyChangeType::kChangedOnlyNonRerasterValues;
return state.Transform().Changed(change, root.Transform()) || if (change_of_decomposited_transforms >= change)
state.Clip().Changed(change, root, &state.Transform()) || return true;
state.Effect().Changed(change, root, &state.Transform());
const auto& root = PropertyTreeState::Root();
return property_tree_state.Transform().Changed(change, root.Transform()) ||
property_tree_state.Clip().Changed(change, root,
&property_tree_state.Transform()) ||
property_tree_state.Effect().Changed(change, root,
&property_tree_state.Transform());
} }
PaintArtifactCompositor::PendingLayer::PendingLayer( PaintArtifactCompositor::PendingLayer::PendingLayer(
...@@ -438,6 +442,9 @@ bool PaintArtifactCompositor::PendingLayer::Merge(const PendingLayer& guest) { ...@@ -438,6 +442,9 @@ bool PaintArtifactCompositor::PendingLayer::Merge(const PendingLayer& guest) {
UniteRectsKnownToBeOpaque(MapRectKnownToBeOpaque(new_state), UniteRectsKnownToBeOpaque(MapRectKnownToBeOpaque(new_state),
guest.MapRectKnownToBeOpaque(new_state)); guest.MapRectKnownToBeOpaque(new_state));
property_tree_state = new_state; property_tree_state = new_state;
change_of_decomposited_transforms =
std::max(change_of_decomposited_transforms,
guest.change_of_decomposited_transforms);
return true; return true;
} }
...@@ -1089,6 +1096,9 @@ void PaintArtifactCompositor::DecompositeTransforms() { ...@@ -1089,6 +1096,9 @@ void PaintArtifactCompositor::DecompositeTransforms() {
while (!transform->IsRoot() && can_be_decomposited.at(transform)) { while (!transform->IsRoot() && can_be_decomposited.at(transform)) {
pending_layer.offset_of_decomposited_transforms += pending_layer.offset_of_decomposited_transforms +=
transform->Translation2D(); transform->Translation2D();
pending_layer.change_of_decomposited_transforms =
std::max(pending_layer.change_of_decomposited_transforms,
transform->NodeChanged());
transform = &transform->Parent()->Unalias(); transform = &transform->Parent()->Unalias();
} }
pending_layer.property_tree_state.SetTransform(*transform); pending_layer.property_tree_state.SetTransform(*transform);
...@@ -1233,7 +1243,7 @@ void PaintArtifactCompositor::Update( ...@@ -1233,7 +1243,7 @@ void PaintArtifactCompositor::Update(
// nodes|^2) and could be optimized by caching the lookup of nodes known // nodes|^2) and could be optimized by caching the lookup of nodes known
// to be changed/unchanged. // to be changed/unchanged.
if (layer->subtree_property_changed() || if (layer->subtree_property_changed() ||
PropertyTreeStateChanged(property_state)) { pending_layer.PropertyTreeStateChanged()) {
layer->SetSubtreePropertyChanged(); layer->SetSubtreePropertyChanged();
root_layer_->SetNeedsCommit(); root_layer_->SetNeedsCommit();
} }
......
...@@ -272,12 +272,16 @@ class PLATFORM_EXPORT PaintArtifactCompositor final ...@@ -272,12 +272,16 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
return compositing_type != kOverlap && compositing_type != kOther; return compositing_type != kOverlap && compositing_type != kOther;
} }
bool PropertyTreeStateChanged() const;
// The rects are in the space of property_tree_state. // The rects are in the space of property_tree_state.
FloatRect bounds; FloatRect bounds;
FloatRect rect_known_to_be_opaque; FloatRect rect_known_to_be_opaque;
PaintChunkSubset chunks; PaintChunkSubset chunks;
PropertyTreeState property_tree_state; PropertyTreeState property_tree_state;
FloatPoint offset_of_decomposited_transforms; FloatPoint offset_of_decomposited_transforms;
PaintPropertyChangeType change_of_decomposited_transforms =
PaintPropertyChangeType::kUnchanged;
const GraphicsLayer* graphics_layer = nullptr; const GraphicsLayer* graphics_layer = nullptr;
CompositingType compositing_type; CompositingType compositing_type;
}; };
...@@ -327,8 +331,6 @@ class PLATFORM_EXPORT PaintArtifactCompositor final ...@@ -327,8 +331,6 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
Vector<scoped_refptr<cc::Layer>>& new_scroll_hit_test_layers, Vector<scoped_refptr<cc::Layer>>& new_scroll_hit_test_layers,
Vector<scoped_refptr<cc::ScrollbarLayerBase>>& new_scrollbar_layers); Vector<scoped_refptr<cc::ScrollbarLayerBase>>& new_scrollbar_layers);
bool PropertyTreeStateChanged(const PropertyTreeState&) const;
const TransformPaintPropertyNode& NearestScrollTranslationForLayer( const TransformPaintPropertyNode& NearestScrollTranslationForLayer(
const PendingLayer&); const PendingLayer&);
......
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