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( ...@@ -1219,7 +1219,7 @@ void SurfaceAggregator::FindChildSurfaces(
RenderPassMapEntry* current_pass_entry, RenderPassMapEntry* current_pass_entry,
const gfx::Transform& transform_to_root_target, const gfx::Transform& transform_to_root_target,
base::flat_map<SurfaceRange, ChildSurfaceInfo>* child_surfaces, 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) { if (current_pass_entry->is_visited) {
// This means that this render pass is an ancestor of itself. This is not // This means that this render pass is an ancestor of itself. This is not
// supported. Stop processing the render pass again. // supported. Stop processing the render pass again.
...@@ -1229,9 +1229,9 @@ void SurfaceAggregator::FindChildSurfaces( ...@@ -1229,9 +1229,9 @@ void SurfaceAggregator::FindChildSurfaces(
RenderPass* render_pass = current_pass_entry->render_pass; RenderPass* render_pass = current_pass_entry->render_pass;
if (current_pass_entry->has_pixel_moving_backdrop_filter) { if (current_pass_entry->has_pixel_moving_backdrop_filter) {
// If the render pass has a backdrop filter that moves pixels, its entire // If the render pass has a backdrop filter that moves pixels, its entire
// bounds, with proper transform applied, should be added to the damage // bounds, with proper transform applied, may be added to the damage
// rect. // rect if it intersects.
pixel_moving_backdrop_filters_rect->Union( pixel_moving_backdrop_filters_rects->push_back(
cc::MathUtil::MapEnclosingClippedRect(transform_to_root_target, cc::MathUtil::MapEnclosingClippedRect(transform_to_root_target,
render_pass->output_rect)); render_pass->output_rect));
} }
...@@ -1296,7 +1296,7 @@ void SurfaceAggregator::FindChildSurfaces( ...@@ -1296,7 +1296,7 @@ void SurfaceAggregator::FindChildSurfaces(
gfx::Transform( gfx::Transform(
transform_to_root_target, transform_to_root_target,
render_pass_quad->shared_quad_state->quad_to_target_transform), 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, ...@@ -1347,10 +1347,10 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
DCHECK(root_pass_it != render_pass_map.end()); DCHECK(root_pass_it != render_pass_map.end());
RenderPassMapEntry& root_pass_entry = root_pass_it->second; RenderPassMapEntry& root_pass_entry = root_pass_it->second;
base::flat_map<SurfaceRange, ChildSurfaceInfo> child_surfaces; 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, FindChildSurfaces(surface->surface_id(), &render_pass_map, &root_pass_entry,
root_pass_transform, &child_surfaces, root_pass_transform, &child_surfaces,
&pixel_moving_backdrop_filters_rect); &pixel_moving_backdrop_filters_rects);
std::vector<ResourceId> referenced_resources; std::vector<ResourceId> referenced_resources;
referenced_resources.reserve(frame.resource_list.size()); referenced_resources.reserve(frame.resource_list.size());
...@@ -1524,8 +1524,18 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface, ...@@ -1524,8 +1524,18 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
if (!damage_rect.IsEmpty() && frame.metadata.may_contain_video) if (!damage_rect.IsEmpty() && frame.metadata.may_contain_video)
result->may_contain_video = true; result->may_contain_video = true;
if (damage_rect.Intersects(pixel_moving_backdrop_filters_rect)) // Repeat this operation until no new render pass with pixel moving backdrop
damage_rect.Union(pixel_moving_backdrop_filters_rect); // 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; return damage_rect;
} }
......
...@@ -206,7 +206,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator { ...@@ -206,7 +206,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
RenderPassMapEntry* current_pass_entry, RenderPassMapEntry* current_pass_entry,
const gfx::Transform& transform_to_root_target, const gfx::Transform& transform_to_root_target,
base::flat_map<SurfaceRange, ChildSurfaceInfo>* child_surfaces, 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, gfx::Rect PrewalkTree(Surface* surface,
bool in_moved_pixel_surface, bool in_moved_pixel_surface,
......
...@@ -5965,5 +5965,136 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassDoesNotFillSurface) { ...@@ -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
} // namespace viz } // 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