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

viz: Use list instead of bounding box for backdrop filter bounds

The surface aggregator when computing the damage rect for a surface
tree, computes a bounding box of all the render pass with backdrop
moving filter. It then uses this bounding box to increase the damage
rect of the root render pass. This causes a larger than needed damage
rect to be set. This patch changes the bounding box logic to that of a
list of rects. The damage rect is then expanded based on if it
intersects with a rect in that list.

      Also added unittests.

Bug: 1031914
Test: Manually tested that partial swap now gives correct damage rect.
Change-Id: I4eb8ff29170ddebfa8be79e9fd885551828af0e3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1965475
Commit-Queue: Malay Keshav <malaykeshav@chromium.org>
Reviewed-by: default avatarkylechar <kylechar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726083}
parent 7052392d
......@@ -1219,7 +1219,7 @@ void SurfaceAggregator::FindChildSurfaces(
RenderPassMapEntry* current_pass_entry,
const gfx::Transform& transform_to_root_target,
base::flat_map<SurfaceRange, ChildSurfaceInfo>* child_surfaces,
gfx::Rect* pixel_moving_backdrop_filters_rect) {
std::vector<gfx::Rect>* pixel_moving_backdrop_filters_rects) {
if (current_pass_entry->is_visited) {
// This means that this render pass is an ancestor of itself. This is not
// supported. Stop processing the render pass again.
......@@ -1229,9 +1229,9 @@ void SurfaceAggregator::FindChildSurfaces(
RenderPass* render_pass = current_pass_entry->render_pass;
if (current_pass_entry->has_pixel_moving_backdrop_filter) {
// If the render pass has a backdrop filter that moves pixels, its entire
// bounds, with proper transform applied, should be added to the damage
// rect.
pixel_moving_backdrop_filters_rect->Union(
// bounds, with proper transform applied, may be added to the damage
// rect if it intersects.
pixel_moving_backdrop_filters_rects->push_back(
cc::MathUtil::MapEnclosingClippedRect(transform_to_root_target,
render_pass->output_rect));
}
......@@ -1296,7 +1296,7 @@ void SurfaceAggregator::FindChildSurfaces(
gfx::Transform(
transform_to_root_target,
render_pass_quad->shared_quad_state->quad_to_target_transform),
child_surfaces, pixel_moving_backdrop_filters_rect);
child_surfaces, pixel_moving_backdrop_filters_rects);
}
}
}
......@@ -1347,10 +1347,10 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
DCHECK(root_pass_it != render_pass_map.end());
RenderPassMapEntry& root_pass_entry = root_pass_it->second;
base::flat_map<SurfaceRange, ChildSurfaceInfo> child_surfaces;
gfx::Rect pixel_moving_backdrop_filters_rect;
std::vector<gfx::Rect> pixel_moving_backdrop_filters_rects;
FindChildSurfaces(surface->surface_id(), &render_pass_map, &root_pass_entry,
root_pass_transform, &child_surfaces,
&pixel_moving_backdrop_filters_rect);
&pixel_moving_backdrop_filters_rects);
std::vector<ResourceId> referenced_resources;
referenced_resources.reserve(frame.resource_list.size());
......@@ -1524,8 +1524,18 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
if (!damage_rect.IsEmpty() && frame.metadata.may_contain_video)
result->may_contain_video = true;
if (damage_rect.Intersects(pixel_moving_backdrop_filters_rect))
damage_rect.Union(pixel_moving_backdrop_filters_rect);
// Repeat this operation until no new render pass with pixel moving backdrop
// filter intersects with the damage rect.
bool did_intersect_damage_rect = true;
while (did_intersect_damage_rect) {
did_intersect_damage_rect = false;
for (const auto& rect : pixel_moving_backdrop_filters_rects) {
if (!damage_rect.Contains(rect) && damage_rect.Intersects(rect)) {
did_intersect_damage_rect = true;
damage_rect.Union(rect);
}
}
}
return damage_rect;
}
......
......@@ -206,7 +206,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
RenderPassMapEntry* current_pass_entry,
const gfx::Transform& transform_to_root_target,
base::flat_map<SurfaceRange, ChildSurfaceInfo>* child_surfaces,
gfx::Rect* pixel_moving_backdrop_filters_rect);
std::vector<gfx::Rect>* pixel_moving_backdrop_filters_rects);
gfx::Rect PrewalkTree(Surface* surface,
bool in_moved_pixel_surface,
......
......@@ -5965,5 +5965,136 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassDoesNotFillSurface) {
}
}
// Tests that damage rects are aggregated correctly when surfaces change.
TEST_F(SurfaceAggregatorValidSurfaceTest,
AggregateDamageRectWithBackdropFilter) {
// Add a callback for when the surface is damaged.
MockAggregatedDamageCallback aggregated_damage_callback;
root_sink_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
std::vector<Quad> solid_color_quad = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(30, 30))};
std::vector<Quad> render_pass_draw_quads = {
Quad::RenderPassQuad(1, gfx::Transform()),
Quad::RenderPassQuad(2, gfx::Transform()),
Quad::RenderPassQuad(3, gfx::Transform()),
Quad::RenderPassQuad(4, gfx::Transform())};
std::vector<Pass> root_passes = {
Pass(solid_color_quad, 1, gfx::Size(30, 30)),
Pass(solid_color_quad, 2, gfx::Size(30, 30)),
Pass(solid_color_quad, 3, gfx::Size(30, 30)),
Pass(solid_color_quad, 4, gfx::Size(30, 30)),
Pass(render_pass_draw_quads, 5, gfx::Size(100, 100))};
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
root_frame.render_pass_list[4]
->shared_quad_state_list.ElementAt(0)
->quad_to_target_transform.Translate(70, 0);
root_frame.render_pass_list[4]
->shared_quad_state_list.ElementAt(1)
->quad_to_target_transform.Translate(30, 30);
root_frame.render_pass_list[4]
->shared_quad_state_list.ElementAt(2)
->quad_to_target_transform.Translate(10, 50);
root_frame.render_pass_list[4]
->shared_quad_state_list.ElementAt(3)
->quad_to_target_transform.Translate(70, 70);
// Add backdrop blur filter to all render passes.
root_frame.render_pass_list[0]->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(5));
root_frame.render_pass_list[1]->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(5));
root_frame.render_pass_list[2]->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(5));
root_frame.render_pass_list[3]->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(5));
root_frame.render_pass_list[4]->damage_rect = gfx::Rect(0, 85, 100, 15);
root_sink_->SubmitCompositorFrame(root_local_surface_id_,
std::move(root_frame));
// Damage rect for first aggregation should contain entire root surface.
SurfaceId root_surface_id(root_sink_->frame_sink_id(),
root_local_surface_id_);
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
gfx::Rect(0, 0, 100, 100), next_display_time()));
CompositorFrame aggregated_frame = AggregateFrame(root_surface_id);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
EXPECT_EQ(gfx::Rect(SurfaceSize()), aggregated_pass_list[4]->damage_rect);
// _____________________
// | | |
// | | |
// | ____ |_____|
// | | | |
// | ___| | |
// | | ||___| |
// | | | _____|
// | |____| | |
// | | |
// |_______________|_____|
//
root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
root_frame.render_pass_list[4]
->shared_quad_state_list.ElementAt(0)
->quad_to_target_transform.Translate(70, 0);
root_frame.render_pass_list[4]
->shared_quad_state_list.ElementAt(1)
->quad_to_target_transform.Translate(30, 30);
root_frame.render_pass_list[4]
->shared_quad_state_list.ElementAt(2)
->quad_to_target_transform.Translate(10, 50);
root_frame.render_pass_list[4]
->shared_quad_state_list.ElementAt(3)
->quad_to_target_transform.Translate(70, 70);
// Add backdrop blur filter to all render passes.
root_frame.render_pass_list[0]->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(5));
root_frame.render_pass_list[1]->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(5));
root_frame.render_pass_list[2]->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(5));
root_frame.render_pass_list[3]->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(5));
// Damage the bottom portion of the root render pass, such that it only
// intersects with one of child render pass.
root_frame.render_pass_list[4]->damage_rect = gfx::Rect(0, 85, 100, 15);
root_sink_->SubmitCompositorFrame(root_local_surface_id_,
std::move(root_frame));
// The expected damage rect should include all the other child render pass
// output surface that would need to be updated. In this case, that would be
// the bottom 3 render pass from the image.
const gfx::Rect expected_damage_rect(0, 30, 100, 70);
SurfaceId root_surface_id_2(root_sink_->frame_sink_id(),
root_local_surface_id_);
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
gfx::Rect(0, 85, 100, 15), next_display_time()));
aggregated_frame = AggregateFrame(root_surface_id_2);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
EXPECT_EQ(expected_damage_rect.ToString(),
aggregated_frame.render_pass_list[4]->damage_rect.ToString());
}
} // namespace
} // namespace viz
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