Commit 25a11f45 authored by Sasha McIntosh's avatar Sasha McIntosh Committed by Commit Bot

viz: Perform occlusion culling on all render passes

Manually tested by deploying to a CrOS device, rotating and casting the screen.
Verified via log statements that occlusion culling is performed.

Test: DisplayTest.DrawOcclusionWithMultipleRenderPass
Bug: 1022544
Change-Id: I389a658699e4e68c5269151ab7be3d6f0e341341
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2139433Reviewed-by: default avatarKhushal <khushalsagar@chromium.org>
Commit-Queue: Sasha McIntosh <sashamcintosh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#760062}
parent 01fdcea8
......@@ -929,11 +929,6 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
if (frame->render_pass_list.empty())
return;
const SharedQuadState* last_sqs = nullptr;
cc::Region occlusion_in_target_space;
cc::Region backdrop_filters_in_target_space;
bool current_sqs_intersects_occlusion = false;
base::flat_map<RenderPassId, gfx::Rect> backdrop_filter_rects;
for (const auto& pass : frame->render_pass_list) {
if (!pass->backdrop_filters.IsEmpty() &&
......@@ -943,11 +938,20 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
}
}
const auto& pass = frame->render_pass_list.back();
// TODO(yiyix): Add filter effects to draw occlusion calculation and perform
// draw occlusion on render pass.
for (const auto& pass : frame->render_pass_list) {
const SharedQuadState* last_sqs = nullptr;
cc::Region occlusion_in_target_space;
cc::Region backdrop_filters_in_target_space;
bool current_sqs_intersects_occlusion = false;
// TODO(yiyix): Add filter effects to draw occlusion calculation
if (!pass->filters.IsEmpty() || !pass->backdrop_filters.IsEmpty())
return;
continue;
// When there is only one quad in the render pass, occlusion is not
// possible.
if (pass->quad_list.size() == 1)
continue;
auto quad_list_end = pass->quad_list.end();
cc::Region occlusion_in_quad_content_space;
......@@ -1058,8 +1062,8 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
}
// A render pass quad may apply some filter or transform to an
// underlying quad. Do not split quads when they intersect with a render
// pass quad.
// underlying quad. Do not split quads when they intersect with a
// render pass quad.
if (current_sqs_in_target_space.Intersects(
backdrop_filters_in_target_space.bounds())) {
for (const auto& rect_in_target_space :
......@@ -1083,7 +1087,8 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
// occlusion region in the quad content space. If |quad| is not
// shown on the screen, then set its rect and visible_rect to be empty.
quad->visible_rect.set_size(gfx::Size());
} else if (occlusion_in_quad_content_space.Intersects(quad->visible_rect)) {
} else if (occlusion_in_quad_content_space.Intersects(
quad->visible_rect)) {
// Case 2: for simple transforms, if the quad is partially shown on
// screen and the region formed by (occlusion region - visible_rect) is
// a rect, then update visible_rect to the resulting rect.
......@@ -1114,8 +1119,8 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
}
} else if (occlusion_in_quad_content_space.IsEmpty() &&
occlusion_in_target_space.Contains(
cc::MathUtil::MapEnclosingClippedRect(transform,
quad->visible_rect))) {
cc::MathUtil::MapEnclosingClippedRect(
transform, quad->visible_rect))) {
// Case 3: for non simple transforms, define the occlusion region in
// target space. If |quad| is not shown on the screen, then set its
// rect and visible_rect to be empty.
......@@ -1123,6 +1128,7 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
}
++quad;
}
}
}
void Display::SetPreferredFrameInterval(base::TimeDelta interval) {
......
......@@ -2568,6 +2568,56 @@ TEST_F(DisplayTest, CompositorFrameWithCombinedSharedQuadState) {
}
}
// Remove overlapping quads in non-root render passes.
TEST_F(DisplayTest, DrawOcclusionWithMultipleRenderPass) {
SetUpGpuDisplay(RendererSettings());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
CompositorFrame frame = CompositorFrameBuilder()
.AddDefaultRenderPass()
.AddDefaultRenderPass()
.Build();
// rect 3 is inside of combined rect of rect 1 and rect 2.
// rect 4 is identical to rect 3, but in a separate render pass.
gfx::Rect rects[4] = {
gfx::Rect(0, 0, 100, 100),
gfx::Rect(100, 0, 60, 60),
gfx::Rect(10, 10, 120, 30),
gfx::Rect(10, 10, 120, 30),
};
SharedQuadState* shared_quad_states[4];
SolidColorDrawQuad* quads[4];
for (int i = 0; i < 4; i++) {
// add all but quad 4 into non-root render pass.
auto& render_pass =
i == 3 ? frame.render_pass_list.back() : frame.render_pass_list.front();
shared_quad_states[i] = render_pass->CreateAndAppendSharedQuadState();
quads[i] =
render_pass->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_states[i]->SetAll(
gfx::Transform(), rects[i], rects[i], gfx::RRectF(), rects[i],
false /*is_clipped*/, true /*are_contents_opaque*/, 1.f /*opacity*/,
SkBlendMode::kSrcOver, 0 /*sorting_context_id*/);
quads[i]->SetNew(shared_quad_states[i], rects[i], rects[i], SK_ColorBLACK,
false /*force_anti_aliasing_off*/);
}
auto& render_pass = frame.render_pass_list.front();
auto& root_render_pass = frame.render_pass_list.back();
EXPECT_EQ(3u, NumVisibleRects(render_pass->quad_list));
EXPECT_EQ(1u, NumVisibleRects(root_render_pass->quad_list));
display_->RemoveOverdrawQuads(&frame);
EXPECT_EQ(2u, NumVisibleRects(render_pass->quad_list));
EXPECT_EQ(1u, NumVisibleRects(root_render_pass->quad_list));
EXPECT_EQ(rects[0], render_pass->quad_list.ElementAt(0)->visible_rect);
EXPECT_EQ(rects[1], render_pass->quad_list.ElementAt(1)->visible_rect);
EXPECT_EQ(rects[3], root_render_pass->quad_list.ElementAt(0)->visible_rect);
}
// Occlusion tracking should not persist across render passes.
TEST_F(DisplayTest, CompositorFrameWithMultipleRenderPass) {
RendererSettings settings;
SetUpGpuDisplay(settings);
......
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