Commit a28a2981 authored by Malay Keshav's avatar Malay Keshav Committed by Commit Bot

cc: Clip render surface damage to its bounds

This patch clips the accumulated damage from a render surface to its
bounds. This is needed for scrollable layers within the render surface
that can have bounds much larger than their render target thus
indirectly contributing to the damage rect of their render target's
render target.

It also removes the expansion of the damage rect based on background
blur filter. This is okay because the background blur is computed within
the bounds of the render surface.

Test=Manually ran chrome os to check for ui glitches.

Bug: 1056014
Change-Id: I942aae3452250540fa283403894078f68630dff0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2075962Reviewed-by: default avatarweiliangc <weiliangc@chromium.org>
Commit-Queue: Malay Keshav <malaykeshav@chromium.org>
Cr-Commit-Position: refs/heads/master@{#749438}
parent 99e7a0aa
...@@ -332,26 +332,6 @@ DamageTracker::DamageAccumulator DamageTracker::TrackDamageFromLeftoverRects() { ...@@ -332,26 +332,6 @@ DamageTracker::DamageAccumulator DamageTracker::TrackDamageFromLeftoverRects() {
return damage; return damage;
} }
void DamageTracker::ExpandDamageInsideRectWithFilters(
const gfx::Rect& pre_filter_rect,
const FilterOperations& filters) {
gfx::Rect damage_rect;
bool is_valid_rect = damage_for_this_update_.GetAsRect(&damage_rect);
// If the damage accumulated so far isn't a valid rect or empty, then there is
// no point in trying to make it bigger.
if (!is_valid_rect || damage_rect.IsEmpty())
return;
// Compute the pixels in the backdrop of the surface that could be affected
// by the damage in the content below.
gfx::Rect expanded_damage_rect = filters.MapRect(damage_rect, SkMatrix::I());
// Restrict it to the rectangle in which the backdrop filter is shown.
expanded_damage_rect.Intersect(pre_filter_rect);
damage_for_this_update_.Union(expanded_damage_rect);
}
void DamageTracker::AccumulateDamageFromLayer(LayerImpl* layer) { void DamageTracker::AccumulateDamageFromLayer(LayerImpl* layer) {
// There are two ways that a layer can damage a region of the target surface: // There are two ways that a layer can damage a region of the target surface:
// 1. Property change (e.g. opacity, position, transforms): // 1. Property change (e.g. opacity, position, transforms):
...@@ -470,24 +450,15 @@ void DamageTracker::AccumulateDamageFromRenderSurface( ...@@ -470,24 +450,15 @@ void DamageTracker::AccumulateDamageFromRenderSurface(
const gfx::Transform& draw_transform = render_surface->draw_transform(); const gfx::Transform& draw_transform = render_surface->draw_transform();
gfx::Rect damage_rect_in_target_space = MathUtil::MapEnclosingClippedRect( gfx::Rect damage_rect_in_target_space = MathUtil::MapEnclosingClippedRect(
draw_transform, damage_rect_in_local_space); draw_transform, damage_rect_in_local_space);
damage_rect_in_target_space.Intersect(
gfx::ToEnclosingRect(render_surface->DrawableContentRect()));
damage_for_this_update_.Union(damage_rect_in_target_space); damage_for_this_update_.Union(damage_rect_in_target_space);
} else if (!is_valid_rect) { } else if (!is_valid_rect) {
damage_for_this_update_.Union(surface_rect_in_target_space); damage_for_this_update_.Union(surface_rect_in_target_space);
} }
} }
// If the layer has a backdrop filter, this may cause pixels in our surface
// to be expanded, so we will need to expand any damage at or below this
// layer. We expand the damage from this layer too, as we need to readback
// those pixels from the surface with only the contents of layers below this
// one in them. This means we need to redraw any pixels in the surface being
// used for the blur in this layer this frame.
const FilterOperations& backdrop_filters = render_surface->BackdropFilters(); const FilterOperations& backdrop_filters = render_surface->BackdropFilters();
if (backdrop_filters.HasFilterThatMovesPixels()) {
ExpandDamageInsideRectWithFilters(surface_rect_in_target_space,
backdrop_filters);
}
if (!surface_is_new && if (!surface_is_new &&
backdrop_filters.HasFilterOfType(FilterOperation::BLUR)) { backdrop_filters.HasFilterOfType(FilterOperation::BLUR)) {
gfx::Rect damage_on_target; gfx::Rect damage_on_target;
......
...@@ -1072,148 +1072,6 @@ TEST_F(DamageTrackerTest, VerifyDamageForHighDPIImageFilter) { ...@@ -1072,148 +1072,6 @@ TEST_F(DamageTrackerTest, VerifyDamageForHighDPIImageFilter) {
EXPECT_EQ(expected_child_damage_rect, child_damage_rect); EXPECT_EQ(expected_child_damage_rect, child_damage_rect);
} }
TEST_F(DamageTrackerTest, VerifyDamageForBackdropBlurredChild) {
LayerImpl* root = CreateAndSetUpTestTreeWithTwoSurfaces();
// Allow us to set damage on child1_ too.
child1_->SetDrawsContent(true);
FilterOperations filters;
filters.Append(FilterOperation::CreateBlurFilter(2.f));
// Setting the filter will damage the whole surface.
ClearDamageForAllSurfaces(root);
SetBackdropFilter(child1_, filters);
child1_->NoteLayerPropertyChanged();
EmulateDrawingOneFrame(root);
// CASE 1: Setting the update rect should cause the corresponding damage to
// the surface, blurred based on the size of the child's backdrop
// blur filter. Note that child1_'s render surface has a size of
// 206x208 due to contributions from grand_child1_ and grand_child2_.
ClearDamageForAllSurfaces(root);
root->UnionUpdateRect(gfx::Rect(297, 297, 2, 2));
EmulateDrawingOneFrame(root);
gfx::Rect root_damage_rect;
EXPECT_TRUE(GetRenderSurface(root)->damage_tracker()->GetDamageRectIfValid(
&root_damage_rect));
// Damage position on the surface should be a composition of the damage on
// the root and on child2_. Damage on the root should be: position of
// update_rect (297, 297), but expanded by the blur outsets.
gfx::Rect expected_damage_rect = gfx::Rect(297, 297, 2, 2);
// 6px spread for a 2px blur.
expected_damage_rect.Inset(-6, -6, -6, -6);
EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
// CASE 2: Setting the update rect should cause the corresponding damage to
// the surface, blurred based on the size of the child's backdrop
// blur filter. Since the damage extends to the right/bottom outside
// of the blurred layer, only the left/top should end up expanded.
ClearDamageForAllSurfaces(root);
root->UnionUpdateRect(gfx::Rect(297, 297, 30, 30));
EmulateDrawingOneFrame(root);
EXPECT_TRUE(GetRenderSurface(root)->damage_tracker()->GetDamageRectIfValid(
&root_damage_rect));
// Damage position on the surface should be a composition of the damage on
// the root and on child2_. Damage on the root should be: position of
// update_rect (297, 297), but expanded on the left/top by the blur outsets.
expected_damage_rect = gfx::Rect(297, 297, 30, 30);
// 6px spread for a 2px blur.
expected_damage_rect.Inset(-6, -6, 0, 0);
EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
// CASE 3: Setting this update rect outside the blurred content_bounds of the
// blurred child1_ will not cause it to be expanded.
ClearDamageForAllSurfaces(root);
root->UnionUpdateRect(gfx::Rect(30, 30, 2, 2));
EmulateDrawingOneFrame(root);
EXPECT_TRUE(GetRenderSurface(root)->damage_tracker()->GetDamageRectIfValid(
&root_damage_rect));
// Damage on the root should be: position of update_rect (30, 30), not
// expanded.
expected_damage_rect = gfx::Rect(30, 30, 2, 2);
EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
// CASE 4: Setting this update rect inside the blurred content_bounds but
// outside the original content_bounds of the blurred child1_ will
// cause it to be expanded.
ClearDamageForAllSurfaces(root);
root->UnionUpdateRect(gfx::Rect(99, 99, 1, 1));
EmulateDrawingOneFrame(root);
EXPECT_TRUE(GetRenderSurface(root)->damage_tracker()->GetDamageRectIfValid(
&root_damage_rect));
// Damage on the root should be: the originally damaged rect (99,99 1x1)
// plus the rect that can influence with a 2px blur (93,93 13x13) intersected
// with the surface rect (100,100 206x208). So no additional damage occurs
// above or to the left, but there is additional damage within the blurred
// area.
expected_damage_rect = gfx::Rect(99, 99, 7, 7);
EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
// CASE 5: Setting the update rect on child2_, which is above child1_, will
// not get blurred by child1_, so it does not need to get expanded.
ClearDamageForAllSurfaces(root);
child2_->UnionUpdateRect(gfx::Rect(1, 1));
EmulateDrawingOneFrame(root);
EXPECT_TRUE(GetRenderSurface(root)->damage_tracker()->GetDamageRectIfValid(
&root_damage_rect));
// Damage on child2_ should be: position of update_rect offset by the child's
// position (11, 11), and not expanded by anything.
expected_damage_rect = gfx::Rect(11, 11, 1, 1);
EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
// CASE 6: Setting the update rect on child1_ will also blur the damage, so
// that any pixels needed for the blur are redrawn in the current
// frame.
ClearDamageForAllSurfaces(root);
child1_->UnionUpdateRect(gfx::Rect(1, 1));
EmulateDrawingOneFrame(root);
EXPECT_TRUE(GetRenderSurface(root)->damage_tracker()->GetDamageRectIfValid(
&root_damage_rect));
// Damage on child1_ should be: position of update_rect offset by the child's
// position (100, 100), and expanded by the damage.
// Damage should be (0,0 1x1), offset by the 100,100 offset of child1_ in
// root, and expanded 6px for the 2px blur (i.e., 94,94 13x13), but there
// should be no damage outside child1_ (i.e. none above or to the left of
// 100,100.
expected_damage_rect = gfx::Rect(100, 100, 7, 7);
EXPECT_EQ(expected_damage_rect.ToString(), root_damage_rect.ToString());
// CASE 7: No changes, so should not damage the surface.
ClearDamageForAllSurfaces(root);
// We want to make sure that the backdrop filter doesn't cause empty damage
// to get expanded. We position child1_ so that an expansion of the empty rect
// would have non-empty intersection with child1_ in its target space (root
// space).
SetPostTranslation(child1_, gfx::Vector2dF());
child1_->NoteLayerPropertyChanged();
// The first call clears the damage caused by the movement.
EmulateDrawingOneFrame(root);
ClearDamageForAllSurfaces(root);
EmulateDrawingOneFrame(root);
gfx::Rect child_damage_rect;
EXPECT_TRUE(GetRenderSurface(root)->damage_tracker()->GetDamageRectIfValid(
&root_damage_rect));
EXPECT_TRUE(GetRenderSurface(child1_)->damage_tracker()->GetDamageRectIfValid(
&child_damage_rect));
// Should not be expanded by the blur filter.
EXPECT_EQ(gfx::Rect(), root_damage_rect);
EXPECT_EQ(gfx::Rect(), child_damage_rect);
}
TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingLayer) { TEST_F(DamageTrackerTest, VerifyDamageForAddingAndRemovingLayer) {
LayerImpl* root = CreateAndSetUpTestTreeWithOneSurface(); LayerImpl* root = CreateAndSetUpTestTreeWithOneSurface();
LayerImpl* child1 = child_layers_[0]; LayerImpl* child1 = child_layers_[0];
......
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