Commit decd40e6 authored by Maggie Chen's avatar Maggie Chen Committed by Commit Bot

Clip the damage rect of the child surface if clipping is on

This is an optimization to reduce the size of damage rect in surface aggregation.
When clipping is on, we should clip the child surface damage rects before adding
them to the parent damage rect.

BUG=900422

Change-Id: Ia85f1d86bf4ba13ac66167c5de04c657d66d175c
Reviewed-on: https://chromium-review.googlesource.com/c/1309318Reviewed-by: default avatarenne <enne@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Reviewed-by: default avatarSunny Sachanandani <sunnyps@chromium.org>
Commit-Queue: Maggie Chen <magchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#605217}
parent ea1a3ea1
......@@ -823,20 +823,25 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
RenderPassId parent_pass_id,
const gfx::Transform& target_to_surface_transform,
const gfx::Rect& quad_rect,
bool stretch_content_to_fill_bounds)
bool stretch_content_to_fill_bounds,
bool is_clipped,
const gfx::Rect& clip_rect_in_root_target_space)
: surface_range(surface_range),
has_moved_pixels(has_moved_pixels),
parent_pass_id(parent_pass_id),
target_to_surface_transform(target_to_surface_transform),
quad_rect(quad_rect),
stretch_content_to_fill_bounds(stretch_content_to_fill_bounds) {}
stretch_content_to_fill_bounds(stretch_content_to_fill_bounds),
is_clipped(is_clipped),
clip_rect_in_root_target_space(clip_rect_in_root_target_space) {}
SurfaceRange surface_range;
bool has_moved_pixels;
RenderPassId parent_pass_id;
gfx::Transform target_to_surface_transform;
gfx::Rect quad_rect;
bool stretch_content_to_fill_bounds;
bool is_clipped;
gfx::Rect clip_rect_in_root_target_space;
};
std::vector<SurfaceInfo> child_surfaces;
......@@ -874,10 +879,21 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
gfx::Transform target_to_surface_transform(
render_pass->transform_to_root_target,
surface_quad->shared_quad_state->quad_to_target_transform);
gfx::Rect clip_rect_in_root_target_space;
if (surface_quad->shared_quad_state->is_clipped) {
// clip_rect is already in quad target space so only
// transform_to_root_target needs to be applied
clip_rect_in_root_target_space =
cc::MathUtil::MapEnclosingClippedRect(
render_pass->transform_to_root_target,
surface_quad->shared_quad_state->clip_rect);
}
child_surfaces.emplace_back(
surface_quad->surface_range, in_moved_pixel_pass, remapped_pass_id,
target_to_surface_transform, surface_quad->rect,
surface_quad->stretch_content_to_fill_bounds);
surface_quad->stretch_content_to_fill_bounds,
surface_quad->shared_quad_state->is_clipped,
clip_rect_in_root_target_space);
} else if (quad->material == DrawQuad::RENDER_PASS) {
const auto* render_pass_quad = RenderPassDrawQuad::MaterialCast(quad);
if (in_moved_pixel_pass) {
......@@ -971,8 +987,14 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
continue;
}
damage_rect.Union(cc::MathUtil::MapEnclosingClippedRect(
surface_info.target_to_surface_transform, surface_damage));
gfx::Rect surface_damage_in_root_target_space =
cc::MathUtil::MapEnclosingClippedRect(
surface_info.target_to_surface_transform, surface_damage);
if (surface_info.is_clipped) {
surface_damage_in_root_target_space.Intersect(
surface_info.clip_rect_in_root_target_space);
}
damage_rect.Union(surface_damage_in_root_target_space);
}
if (!damage_rect.IsEmpty()) {
......
......@@ -37,6 +37,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/rect_conversions.h"
namespace viz {
namespace {
......@@ -363,9 +364,7 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
SurfaceId(support_->frame_sink_id(), root_local_surface_id_));
}
void TearDown() override {
SurfaceAggregatorTest::TearDown();
}
void TearDown() override { SurfaceAggregatorTest::TearDown(); }
// Verifies that if the |SharedQuadState::quad_layer_rect| can be covered by
// |DrawQuad::Rect| in the SharedQuadState.
......@@ -2909,7 +2908,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SurfaceDamageDifferentFrameSinkId) {
EXPECT_TRUE(aggregator_.NotifySurfaceDamageAndCheckForDisplayDamage(
SurfaceId(kArbitraryFrameSinkId2, id4)));
// This FrameSinkId is not embedded at all so it shouldn't damage the display.
EXPECT_FALSE(aggregator_.NotifySurfaceDamageAndCheckForDisplayDamage(
SurfaceId(kArbitraryFrameSinkId3, id4)));
......@@ -4253,6 +4251,105 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
}
}
// Tests that the damage rect from a child surface is clipped before
// aggregated with the parent damage rect when clipping is on
TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithClippedChildSurface) {
std::vector<Quad> child_surface_quads = {
Quad::SolidColorQuad(SK_ColorRED, gfx::Rect(SurfaceSize()))};
std::vector<Pass> child_surface_passes = {
Pass(child_surface_quads, 1, SurfaceSize())};
CompositorFrame child_surface_frame = MakeEmptyCompositorFrame();
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
allocator_.GenerateId();
LocalSurfaceId child_local_surface_id = allocator_.GetCurrentLocalSurfaceId();
SurfaceId child_surface_id(child_support_->frame_sink_id(),
child_local_surface_id);
child_support_->SubmitCompositorFrame(child_local_surface_id,
std::move(child_surface_frame));
// root surface quads
std::vector<Quad> root_surface_quads = {
Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(SurfaceSize()), false)};
std::vector<Pass> root_passes = {Pass(root_surface_quads, 1, SurfaceSize())};
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_);
support_->SubmitCompositorFrame(root_local_surface_id_,
std::move(root_frame));
// The damage rect of the very first frame is always the full rect
CompositorFrame aggregated_frame =
aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement());
// Parameters used for damage rect testing
gfx::Transform transform(0.5, 0, 0, 0.5, 20, 0);
gfx::Rect clip_rect = gfx::Rect(30, 30, 40, 40);
// Clipping is off
{
CompositorFrame child_surface_frame = MakeEmptyCompositorFrame();
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
child_support_->SubmitCompositorFrame(child_local_surface_id,
std::move(child_surface_frame));
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
auto* root_render_pass = root_frame.render_pass_list[0].get();
auto* surface_quad_sqs = root_render_pass->shared_quad_state_list.front();
surface_quad_sqs->quad_to_target_transform = transform;
surface_quad_sqs->is_clipped = false;
// Set the root damage rect to empty. Only the child surface will be tested.
root_render_pass->damage_rect = gfx::Rect();
support_->SubmitCompositorFrame(root_local_surface_id_,
std::move(root_frame));
CompositorFrame aggregated_frame = aggregator_.Aggregate(
root_surface_id, GetNextDisplayTimeAndIncrement());
// The root damage rect should be the size of the child surface damage rect
gfx::Rect expected_damage_rect(20, 0, 50, 50);
EXPECT_EQ(aggregated_frame.render_pass_list[0]->damage_rect,
expected_damage_rect);
}
// Clipping is on
{
CompositorFrame child_surface_frame = MakeEmptyCompositorFrame();
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
child_support_->SubmitCompositorFrame(child_local_surface_id,
std::move(child_surface_frame));
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
auto* root_render_pass = root_frame.render_pass_list[0].get();
auto* surface_quad_sqs = root_render_pass->shared_quad_state_list.front();
surface_quad_sqs->quad_to_target_transform = transform;
surface_quad_sqs->is_clipped = true;
surface_quad_sqs->clip_rect = clip_rect;
root_render_pass->damage_rect = gfx::Rect();
support_->SubmitCompositorFrame(root_local_surface_id_,
std::move(root_frame));
CompositorFrame aggregated_frame = aggregator_.Aggregate(
root_surface_id, GetNextDisplayTimeAndIncrement());
// The root damage rect should be the size of the clipped child surface
// damage rect
gfx::Rect expected_damage_rect(30, 30, 40, 20);
EXPECT_EQ(aggregated_frame.render_pass_list[0]->damage_rect,
expected_damage_rect);
}
}
// Tests that quads outside the damage rect are not ignored for cached render
// pass.
TEST_F(SurfaceAggregatorPartialSwapTest, NotIgnoreOutsideForCachedRenderPass) {
......
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