Commit f38119e6 authored by yjliu's avatar yjliu Committed by Commit Bot

Fixed the flickering when pixel-moving backdrop filters are present.

The problem was caused by the expansion of damage under the pixel-moving
backdrop filters didn't take into account the damage coming from an
earlier stage (cc) in the pipeline.

Bug: 1107376
Change-Id: Ie734cdbec910b17bb4b12fc9f209345e04ad12e7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2310389
Commit-Queue: Jun Liu <yjliu@chromium.org>
Reviewed-by: default avatarkylechar <kylechar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#791448}
parent e2fb697b
......@@ -1229,6 +1229,7 @@ gfx::Rect SurfaceAggregator::PrewalkRenderPass(
base::flat_map<RenderPassId, RenderPassMapEntry>* render_pass_map,
bool will_draw,
const gfx::Rect& damage_from_parent,
const gfx::Transform& target_to_root_transform,
PrewalkResult* result) {
if (render_pass_entry->is_visited) {
// This render pass is an ancestor of itself and is not supported.
......@@ -1255,11 +1256,25 @@ gfx::Rect SurfaceAggregator::PrewalkRenderPass(
has_pixel_moving_filter ||
base::Contains(moved_pixel_passes_, remapped_pass_id);
gfx::Transform root_to_target_transform(gfx::Transform::kSkipInitialization);
const bool transform_inverted =
target_to_root_transform.GetInverse(&root_to_target_transform);
DCHECK(transform_inverted);
const CompositorFrame& frame = surface->GetActiveFrame();
RenderPass* last_pass = frame.render_pass_list.back().get();
gfx::Rect full_damage = last_pass->output_rect;
gfx::Rect damage_rect_for_surface =
// The damage on the root render pass of the surface comes from damage
// accumulated from all quads in the surface, and needs to be expanded by any
// pixel-moving backdrop filter in the render pass if intersecting. Transform
// this damage into the local space of the render pass for this purpose.
gfx::Rect surface_root_rp_damage =
DamageRectForSurface(surface, *last_pass, full_damage);
if (!surface_root_rp_damage.IsEmpty()) {
surface_root_rp_damage = cc::MathUtil::ProjectEnclosingClippedRect(
root_to_target_transform, surface_root_rp_damage);
}
gfx::Rect damage_rect;
// Iterate through the quad list back-to-front and accumulate damage from
......@@ -1298,19 +1313,20 @@ gfx::Rect SurfaceAggregator::PrewalkRenderPass(
// If the surface quad is to be merged potentially, the current
// effective accumulated damage needs to be taken into account. This
// includes the damage from quads under the surface quad, i.e.
// |damage_rect|, |damage_rect_for_surface| and |damage_from_parent|.
// The damage is first transformed into the local space of the surface
// quad and then passed to the embedding surface. The condition for
// deciding if the surface quad will merge is loose here, so for those
// quads passed this condition but eventually don't merge, there is
// over-contribution of the damage passed from parent, but this
// shouldn't affect correctness.
// |damage_rect|, |surface_root_rp_damage|, which can contain damage
// contributed by quads under the surface quad in the previous stage
// (cc), and |damage_from_parent|. The damage is first transformed into
// the local space of the surface quad and then passed to the embedding
// surface. The condition for deciding if the surface quad will merge is
// loose here, so for those quads passed this condition but eventually
// don't merge, there is over-contribution of the damage passed from
// parent, but this shouldn't affect correctness.
gfx::Rect accumulated_damage_in_child_space;
if (CanPotentiallyMergePass(*surface_quad)) {
accumulated_damage_in_child_space.Union(damage_rect);
accumulated_damage_in_child_space.Union(damage_from_parent);
accumulated_damage_in_child_space.Union(damage_rect_for_surface);
accumulated_damage_in_child_space.Union(surface_root_rp_damage);
if (!accumulated_damage_in_child_space.IsEmpty()) {
gfx::Transform inverse(gfx::Transform::kSkipInitialization);
bool inverted =
......@@ -1334,7 +1350,8 @@ gfx::Rect SurfaceAggregator::PrewalkRenderPass(
continue;
if (in_moved_pixel_pass) {
damage_rect = full_damage;
damage_rect = cc::MathUtil::ProjectEnclosingClippedRect(
root_to_target_transform, full_damage);
continue;
}
} else if (quad->material == DrawQuad::Material::kRenderPass) {
......@@ -1351,16 +1368,19 @@ gfx::Rect SurfaceAggregator::PrewalkRenderPass(
quad->shared_quad_state->quad_to_target_transform,
child_render_pass.output_rect);
// Both |damage_rect| and |damage_from_parent| are from under the quad,
// so if they intersect the quad render pass output rect, we have to
// invalidate the |can_use_backdrop_filter_cache| flag. Note the
// intersection test can be done against backdrop filter bounds as an
// improvement.
// |damage_rect|, |damage_from_parent| and |surface_root_rp_damage|
// either are or can possible contain damage from under the quad, so if
// they intersect the quad render pass output rect, we have to invalidate
// the |can_use_backdrop_filter_cache| flag. Note the intersection test
// can be done against backdrop filter bounds as an improvement.
bool intersects_current_damage =
rect_in_target_space.Intersects(damage_rect);
bool intersects_damage_from_parent =
rect_in_target_space.Intersects(damage_from_parent);
if (intersects_current_damage || intersects_damage_from_parent) {
bool intersects_damage_from_surface =
rect_in_target_space.Intersects(surface_root_rp_damage);
if (intersects_current_damage || intersects_damage_from_parent ||
intersects_damage_from_surface) {
render_pass_quad->can_use_backdrop_filter_cache = false;
if (child_render_pass.backdrop_filters.HasFilterThatMovesPixels()) {
......@@ -1368,12 +1388,16 @@ gfx::Rect SurfaceAggregator::PrewalkRenderPass(
// rect and it has to be expanded because of the pixel-moving
// backdrop filters. We expand the |damage_rect| to include quad
// render pass output rect (which can be optimized to be backdrop
// filter bounds). |damage_from_parent| only has to be included when
// it also has intersection with the quad.
// filter bounds). |damage_from_parent| and |surface_root_rp_damage|
// only have to be included when they also have intersection with the
// quad.
damage_rect.Union(rect_in_target_space);
if (intersects_damage_from_parent) {
damage_rect.Union(damage_from_parent);
}
if (intersects_damage_from_surface) {
damage_rect.Union(surface_root_rp_damage);
}
}
}
......@@ -1384,9 +1408,13 @@ gfx::Rect SurfaceAggregator::PrewalkRenderPass(
render_pass_dependencies_[remapped_pass_id].insert(
remapped_child_pass_id);
quad_damage_rect =
PrewalkRenderPass(&child_render_pass_entry, surface, render_pass_map,
will_draw, gfx::Rect(), result);
const gfx::Transform child_to_root_transform(
target_to_root_transform,
quad->shared_quad_state->quad_to_target_transform);
quad_damage_rect = PrewalkRenderPass(
&child_render_pass_entry, surface, render_pass_map, will_draw,
gfx::Rect(), child_to_root_transform, result);
} else {
continue;
......@@ -1486,7 +1514,8 @@ gfx::Rect SurfaceAggregator::PrewalkSurface(Surface* surface,
RenderPassMapEntry& entry = it->second;
damage_rect.Union(PrewalkRenderPass(&entry, surface, &render_pass_map,
will_draw, damage_from_parent, result));
will_draw, damage_from_parent,
gfx::Transform(), result));
damage_rect = cc::MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(
root_pass_transform, damage_rect);
......
......@@ -204,6 +204,8 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
// the surface quad in the render pass merged to, plus its |damage_rect|
// and damage passed onto it by its parent if any.
// If there's no merging of |surface|, |accummulated_damage| is empty.
// - |target_to_root_transform| is the transform from current render pass to
// the root.
// - |result| is the result of a prewalk of the surface that contains the
// render pass.
gfx::Rect PrewalkRenderPass(
......@@ -212,6 +214,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
base::flat_map<RenderPassId, RenderPassMapEntry>* render_pass_map,
bool will_draw,
const gfx::Rect& damage_from_parent,
const gfx::Transform& target_to_root_transform,
PrewalkResult* result);
// Walk the Surface tree from |surface|. Validate the resources of the
......
......@@ -3725,6 +3725,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
root_frame.render_pass_list.back()
->shared_quad_state_list.front()
->quad_to_target_transform.Translate(20, 30);
root_frame.render_pass_list.back()->damage_rect = gfx::Rect();
root_sink_->SubmitCompositorFrame(root_local_surface_id_,
std::move(root_frame));
SurfaceId root_surface_id(root_sink_->frame_sink_id(),
......@@ -3753,9 +3754,9 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
aggregated_pass_list.back()->damage_rect);
const auto* quad_to_test = aggregated_pass_list.back()->quad_list.front();
const auto* rp_quad = RenderPassDrawQuad::MaterialCast(quad_to_test);
// The |quad_to_test| (20,30 80x80) intersects with damage below from the
// surface quad (0,0 70x70), so its |can_use_backdrop_filter_cache| is reset
// to false.
// The |quad_to_test| (20,30 80x80) intersects with damage below, which is
// union of surface quad damage (0,0 70x70) and root surface damage (0,0
// 100x100), so its |can_use_backdrop_filter_cache| is reset to false.
EXPECT_FALSE(rp_quad->can_use_backdrop_filter_cache);
}
......@@ -3769,13 +3770,13 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
root_frame.render_pass_list.back()
->shared_quad_state_list.front()
->quad_to_target_transform.Translate(20, 30);
root_frame.render_pass_list.back()->damage_rect = gfx::Rect();
root_sink_->SubmitCompositorFrame(root_local_surface_id_,
std::move(root_frame));
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, _, _, _))
.Times(0);
// No damage is expected from the child surface.
EXPECT_CALL(aggregated_damage_callback,
......@@ -3787,8 +3788,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
EXPECT_EQ(gfx::Rect(SurfaceSize()),
aggregated_pass_list.back()->damage_rect);
EXPECT_EQ(gfx::Rect(), aggregated_pass_list.back()->damage_rect);
const auto* quad_to_test = aggregated_pass_list.back()->quad_list.front();
const auto* rp_quad = RenderPassDrawQuad::MaterialCast(quad_to_test);
// No damage under |quad_to_test| and its |can_use_backdrop_filter_cache|
......@@ -3904,6 +3904,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
CompositorFrame child_frame = MakeEmptyCompositorFrame();
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
child_frame.render_pass_list.back()->damage_rect = gfx::Rect();
ParentLocalSurfaceIdAllocator child_allocator;
child_allocator.GenerateId();
......@@ -3999,15 +4000,16 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
const auto* rp_quad = RenderPassDrawQuad::MaterialCast(quad_to_test);
// 1) Without merging, the |quad_to_test| (or more precisely, the
// |output_rect| of the render pass referenced by the quad that's used for
// damage intersection test) (0,0 60x60) has no damage below, so its
// |can_use_backdrop_filter_cache| remains true. 2) With merging, the
// |quad_to_test| would be merged to the root pass of the root surface. The
// damage from below (0,0 100x100), which is the total of the damage from
// second surface quad (0,0 80x80) and from root render pass (0,0 100x100),
// is transformed into the local space of the child surface as (-20,-30
// 100x100) and it intersects |quad_to_test|(0,0 60x60), so its
// |can_use_backdrop_filter_cache| resets to false.
EXPECT_EQ(!AllowMerge(), rp_quad->can_use_backdrop_filter_cache);
// damage intersection test) (0,0 60x60) has damage below from surface root
// render pass (0,0 60x60), so its |can_use_backdrop_filter_cache| resets
// to false.
// 2) With merging, the |quad_to_test| would be merged to the root pass of
// the root surface. The damage from below (0,0 100x100), which is the total
// of the damage from second surface quad (0,0 80x80) and from root render
// pass (0,0 100x100), is transformed into the local space of the child
// surface as (-20,-30 100x100) and it intersects |quad_to_test|(0,0 60x60),
// so its |can_use_backdrop_filter_cache| resets to false.
EXPECT_FALSE(rp_quad->can_use_backdrop_filter_cache);
}
// Resubmit child frame and since there'll be no damage under the RPDQ with
......@@ -4017,21 +4019,17 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
CompositorFrame child_frame = MakeEmptyCompositorFrame();
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
child_frame.render_pass_list.back()->damage_rect = gfx::Rect();
child_sink_->SubmitCompositorFrame(child_local_surface_id,
std::move(child_frame));
const gfx::Rect expected_damage_rect(20, 30, 60, 60);
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
expected_damage_rect, next_display_time()));
OnAggregatedDamage(root_local_surface_id_, _, _, _))
.Times(0);
// 1) Without merging, the damage for the child surface should be
// the entire child surface (0,0 60x60).
// 2) With merging, because there's no damage passed from the parent,
// the damage for the child surface is its own rect (0,0 60x60).
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(child_local_surface_id, child_surface_size,
gfx::Rect(child_surface_size), next_display_time()));
// There should be no damage on any surface.
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(child_local_surface_id, _, _, _))
.Times(0);
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(second_local_surface_id, _, _, _))
......@@ -4042,7 +4040,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
EXPECT_EQ(expected_damage_rect, aggregated_pass_list.back()->damage_rect);
EXPECT_EQ(gfx::Rect(), aggregated_pass_list.back()->damage_rect);
const auto* quad_to_test =
aggregated_pass_list[AllowMerge() ? 2 : 1]->quad_list.front();
const auto* rp_quad = RenderPassDrawQuad::MaterialCast(quad_to_test);
......@@ -4132,10 +4130,9 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// 1) Without merging, the |quad_to_test| (0,0 60x60) doesn't have any
// damage from under it and its |can_use_backdrop_filter_cache| remains
// unchanged (true).
// 2) With merging, the |quad_to_test| (0,0 60x60)
// intersects the damage passed on from second surface and transformed into
// the child local space (40,30 10x10) and its
// |can_use_backdrop_filter_cache| resets to false.
// 2) With merging, the |quad_to_test| (0,0 60x60) intersects the damage
// passed on from second surface and transformed into the child local space
// (40,30 10x10) and its |can_use_backdrop_filter_cache| resets to false.
EXPECT_EQ(!AllowMerge(), rp_quad->can_use_backdrop_filter_cache);
}
}
......@@ -4144,17 +4141,23 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// updated correctly with surface damage.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
RPDQCanUseBackdropFilterCache) {
auto parent_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot);
// Add a callback for when the surface is damaged.
MockAggregatedDamageCallback aggregated_damage_callback;
root_sink_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
child_sink_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
parent_support->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
auto parent_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot);
constexpr gfx::Size child_surface_size(80, 80);
std::vector<Quad> child_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> child_passes = {
Pass(child_quads, RenderPassId{1}, gfx::Size(80, 80))};
Pass(child_quads, RenderPassId{1}, child_surface_size)};
CompositorFrame child_frame = MakeEmptyCompositorFrame();
AddPasses(&child_frame.render_pass_list, child_passes,
......@@ -4173,11 +4176,12 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
child_sink_->SubmitCompositorFrame(child_local_surface_id,
std::move(child_frame));
constexpr gfx::Size parent_surface_size(90, 90);
std::vector<Quad> parent_surface_quads = {Quad::SurfaceQuad(
SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false, AllowMerge())};
std::vector<Pass> parent_surface_passes = {
Pass(parent_surface_quads, RenderPassId{1}, gfx::Size(90, 90))};
Pass(parent_surface_quads, RenderPassId{1}, parent_surface_size)};
// Parent surface is only used to test if the transform is applied correctly
// to the child surface's damage.
......@@ -4235,7 +4239,15 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
gfx::Rect(0, 0, 100, 100), next_display_time()));
gfx::Rect(SurfaceSize()), next_display_time()));
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(child_local_surface_id, child_surface_size,
gfx::Rect(child_surface_size), next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(parent_local_surface_id, parent_surface_size,
gfx::Rect(parent_surface_size),
next_display_time()));
auto aggregated_frame = AggregateFrame(root_surface_id);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
......@@ -4246,7 +4258,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
EXPECT_EQ(gfx::Rect(SurfaceSize()),
aggregated_pass_list.back()->damage_rect);
// The damage rect from under |quad_to_test| (0,0 90x90) intersects quad
// The damage rect from under |quad_to_test| (0,0 100x100) intersects quad
// render pass output rect (0,0 50x50).
const auto* quad_to_test = aggregated_pass_list.back()->quad_list.front();
const auto* rp_quad = RenderPassDrawQuad::MaterialCast(quad_to_test);
......@@ -4259,12 +4271,18 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
root_frame.render_pass_list.back()->damage_rect = gfx::Rect();
root_sink_->SubmitCompositorFrame(root_local_surface_id_,
std::move(root_frame));
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
gfx::Rect(0, 0, 100, 100), next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, _, _, _))
.Times(0);
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(child_local_surface_id, _, _, _))
.Times(0);
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(parent_local_surface_id, _, _, _))
.Times(0);
auto aggregated_frame = AggregateFrame(root_surface_id);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
......@@ -4298,6 +4316,13 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
expected_damage_rect, next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(child_local_surface_id, child_surface_size,
expected_damage_rect, next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(parent_local_surface_id, parent_surface_size,
expected_damage_rect, next_display_time()));
auto aggregated_frame = AggregateFrame(root_surface_id);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
......@@ -4318,12 +4343,18 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
root_frame.render_pass_list.back()->damage_rect = gfx::Rect();
root_sink_->SubmitCompositorFrame(root_local_surface_id_,
std::move(root_frame));
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
gfx::Rect(0, 0, 100, 100), next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, _, _, _))
.Times(0);
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(child_local_surface_id, _, _, _))
.Times(0);
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(parent_local_surface_id, _, _, _))
.Times(0);
auto aggregated_frame = AggregateFrame(root_surface_id);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
......@@ -4349,12 +4380,15 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
MockAggregatedDamageCallback aggregated_damage_callback;
root_sink_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
child_sink_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
// The child surface consists of a single render pass containing a single
// solid color draw quad.
const gfx::Size child_surface_size(SurfaceSize());
std::vector<Quad> child_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> child_passes = {Pass(child_quads, SurfaceSize())};
std::vector<Pass> child_passes = {Pass(child_quads, child_surface_size)};
CompositorFrame child_frame = MakeEmptyCompositorFrame();
AddPasses(&child_frame.render_pass_list, child_passes,
......@@ -4417,11 +4451,19 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
std::move(root_frame));
// Damage rect for the first aggregation would contain entire root surface
// which is union of (0,0 100x100) and (30,50 200x200), i.e. (0,0 230x250).
// which is union of (0,0 100x100) from RP1, (0,0 200x200) from RP2 and
// (0,0 230x250) from RP3, a total of (0,0 230x250).
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
gfx::Rect(0, 0, 230, 250), next_display_time()));
// The child surface is embedded twice so the callback is called twice.
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(child_local_surface_id, child_surface_size,
gfx::Rect(child_surface_size), next_display_time()))
.Times(2);
auto aggregated_frame = AggregateFrame(root_surface_id);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
ASSERT_EQ(expected_num_passes_after_aggregation,
......@@ -4441,14 +4483,16 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
root_frame.render_pass_list.back()->damage_rect = gfx::Rect();
root_sink_->SubmitCompositorFrame(root_local_surface_id_,
std::move(root_frame));
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
gfx::Rect(0, 0, 100, 100), next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, _, _, _))
.Times(0);
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(child_local_surface_id, _, _, _))
.Times(0);
auto aggregated_frame = AggregateFrame(root_surface_id);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
......@@ -4477,8 +4521,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// The child surface is embedded twice in the root surface, so its damage
// rect would appear in two locations in the root surface:
// 1) The first embedding has no transform, so its damage rect would
// simply
// be (10,10 10x10).
// simply be (10,10 10x10).
// 2) The second embedding is scaled by a factor of 2 and translated by
// (30,50). So, its damage rect would be (10*2+30,10*2+50 10*2x10*2) =
// (50,70 20x20).
......@@ -4489,10 +4532,16 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// The aggregated damage rect would be union of the above damage rects
// which is (10,10 60x80).
gfx::Rect expected_damage_rect(10, 10, 60, 80);
constexpr gfx::Rect expected_damage_rect(10, 10, 60, 80);
constexpr gfx::Rect expected_child_damage_rect(10, 10, 10, 10);
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
expected_damage_rect, next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(child_local_surface_id, child_surface_size,
gfx::Rect(expected_child_damage_rect),
next_display_time()))
.Times(2);
auto aggregated_frame_2 = AggregateFrame(root_surface_id);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
......@@ -4523,14 +4572,21 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
root_frame.render_pass_list.back()->damage_rect = gfx::Rect();
root_sink_->SubmitCompositorFrame(root_local_surface_id_,
std::move(root_frame));
gfx::Rect expected_damage_rect(0, 0, 100, 100);
constexpr gfx::Rect expected_damage_rect(10, 10, 60, 80);
constexpr gfx::Rect expected_child_damage_rect(10, 10, 10, 10);
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
expected_damage_rect, next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
OnAggregatedDamage(child_local_surface_id, child_surface_size,
gfx::Rect(expected_child_damage_rect),
next_display_time()))
.Times(2);
auto aggregated_frame_2 = AggregateFrame(root_surface_id);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
......@@ -4557,7 +4613,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
aggregated_damage_callback.GetCallback());
gfx::Size child_surface_size(60, 60);
// The child surface has two passes:
// The child surface has three passes:
// - the first pass contains solid color quad.
// - the second pass contains a render pass quad referencing the first pass
// with a blur backdrop filter.
......@@ -4627,16 +4683,16 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
// 1) Without merging, the damage for the first aggregation should contain
// the entire child surface (0,0 60x60).
// 2) With merging, in the local space of the root pass of the child frame,
// the second render pass (20,30 60x60) has a blur backdrop
// filter. It expands the damage passed from parent surface and transformed
// into the same local space to (-5,-5 100x100), so the child surface has a
// damage rect of (-5,-5 100x100).
gfx::Rect expected_child_damage_rect = AllowMerge()
? gfx::Rect(-5, -5, 100, 100)
: gfx::Rect(child_surface_size);
// In the local space of the root pass of the child frame, the second render
// pass (20,30 60x60) has a blur backdrop filter. It expands the damage from
// under it. 1) Without merging, the damage for the first aggregation of the
// child surface is the entire child surface (0,0 60x60), expanded by the
// backdrop filter, to be (0,0 80x90).
// 2) With merging, the backdrop filter expands the damage passed from
// parent surface and transformed into the root pass local space to (-5,-5
// 100x100), so the child surface has a damage rect of (-5,-5 100x100).
gfx::Rect expected_child_damage_rect =
AllowMerge() ? gfx::Rect(-5, -5, 100, 100) : gfx::Rect(0, 0, 80, 90);
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(child_local_surface_id, child_surface_size,
......@@ -4697,7 +4753,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
aggregated_damage_callback.GetCallback());
gfx::Size child_surface_size(60, 60);
// The child surface has two passes:
// The child surface has three passes:
// - the first pass contains solid color quad.
// - the second pass contains a render pass quad referencing the first pass
// with a blur backdrop filter.
......@@ -4762,27 +4818,28 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
size_t expected_num_passes_after_aggregation = AllowMerge() ? 3u : 4u;
// First aggregation.
{
// 1) Without merging, the damage for the first aggregation should contain
// the entire child surface (0,0 60x60).
// 2) With merging, in the local space of the root pass of the child frame,
// the second render pass (20,30 60x60) has a blur backdrop filter. It
// expands the damage passed from parent surface and transformed into the
// same local space to (-5,-5 100x100), scaled by 2/3 to (-4,-4 68x68), so
// the child surface has a damage rect of (-4,-4 84x94).
gfx::Rect expected_child_damage_rect = AllowMerge()
? gfx::Rect(-4, -4, 84, 94)
: gfx::Rect(child_surface_size);
// In the local space of the root pass of the child frame, the second render
// pass (20,30 60x60) has a blur backdrop filter. It expands the damage from
// under it. 1) Without merging, the damage for the first aggregation of the
// child surface is the entire child surface (0,0 60x60), expanded by the
// backdrop filter, to be (0,0 80x90).
// 2) With merging, the damage from parent surface is transformed into the
// root pass local space to (-5,-5 100x100), and scaled by 2/3 to (-4,-4
// 68x68). The backdrop filter expands this damage to (-4,-4, 84x94).
gfx::Rect expected_child_damage_rect =
AllowMerge() ? gfx::Rect(-4, -4, 84, 94) : gfx::Rect(0, 0, 80, 90);
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(child_local_surface_id, child_surface_size,
expected_child_damage_rect, next_display_time()));
// 1) Without merging, root surface damage should contain the entire root
// rect.
// 1) Without merging, child surface damage (0,0 80x90) stretches to (0,0
// 120x135), and transformed to root surface as (5,5 120x135), unions root
// surface damage (0,0 100,100) to (0,0 125x140).
// 2) With merging, child surface damage (-4,-4 84x94) stretches to (-6,-6
// 126x141), and transformed to root surface as (-1,-1 126x141).
gfx::Rect expected_root_damage_rect =
AllowMerge() ? gfx::Rect(-1, -1, 126, 141) : gfx::Rect(SurfaceSize());
AllowMerge() ? gfx::Rect(-1, -1, 126, 141) : gfx::Rect(0, 0, 125, 140);
EXPECT_CALL(
aggregated_damage_callback,
OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
......
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