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) { ...@@ -929,11 +929,6 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
if (frame->render_pass_list.empty()) if (frame->render_pass_list.empty())
return; 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; base::flat_map<RenderPassId, gfx::Rect> backdrop_filter_rects;
for (const auto& pass : frame->render_pass_list) { for (const auto& pass : frame->render_pass_list) {
if (!pass->backdrop_filters.IsEmpty() && if (!pass->backdrop_filters.IsEmpty() &&
...@@ -943,11 +938,20 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) { ...@@ -943,11 +938,20 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
} }
} }
const auto& pass = frame->render_pass_list.back(); for (const auto& pass : frame->render_pass_list) {
// TODO(yiyix): Add filter effects to draw occlusion calculation and perform const SharedQuadState* last_sqs = nullptr;
// draw occlusion on render pass. 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()) 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(); auto quad_list_end = pass->quad_list.end();
cc::Region occlusion_in_quad_content_space; cc::Region occlusion_in_quad_content_space;
...@@ -1058,8 +1062,8 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) { ...@@ -1058,8 +1062,8 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
} }
// A render pass quad may apply some filter or transform to an // A render pass quad may apply some filter or transform to an
// underlying quad. Do not split quads when they intersect with a render // underlying quad. Do not split quads when they intersect with a
// pass quad. // render pass quad.
if (current_sqs_in_target_space.Intersects( if (current_sqs_in_target_space.Intersects(
backdrop_filters_in_target_space.bounds())) { backdrop_filters_in_target_space.bounds())) {
for (const auto& rect_in_target_space : for (const auto& rect_in_target_space :
...@@ -1083,7 +1087,8 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) { ...@@ -1083,7 +1087,8 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
// occlusion region in the quad content space. If |quad| is not // 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. // shown on the screen, then set its rect and visible_rect to be empty.
quad->visible_rect.set_size(gfx::Size()); 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 // Case 2: for simple transforms, if the quad is partially shown on
// screen and the region formed by (occlusion region - visible_rect) is // screen and the region formed by (occlusion region - visible_rect) is
// a rect, then update visible_rect to the resulting rect. // a rect, then update visible_rect to the resulting rect.
...@@ -1114,8 +1119,8 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) { ...@@ -1114,8 +1119,8 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
} }
} else if (occlusion_in_quad_content_space.IsEmpty() && } else if (occlusion_in_quad_content_space.IsEmpty() &&
occlusion_in_target_space.Contains( occlusion_in_target_space.Contains(
cc::MathUtil::MapEnclosingClippedRect(transform, cc::MathUtil::MapEnclosingClippedRect(
quad->visible_rect))) { transform, quad->visible_rect))) {
// Case 3: for non simple transforms, define the occlusion region in // Case 3: for non simple transforms, define the occlusion region in
// target space. If |quad| is not shown on the screen, then set its // target space. If |quad| is not shown on the screen, then set its
// rect and visible_rect to be empty. // rect and visible_rect to be empty.
...@@ -1123,6 +1128,7 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) { ...@@ -1123,6 +1128,7 @@ void Display::RemoveOverdrawQuads(CompositorFrame* frame) {
} }
++quad; ++quad;
} }
}
} }
void Display::SetPreferredFrameInterval(base::TimeDelta interval) { void Display::SetPreferredFrameInterval(base::TimeDelta interval) {
......
...@@ -2568,6 +2568,56 @@ TEST_F(DisplayTest, CompositorFrameWithCombinedSharedQuadState) { ...@@ -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) { TEST_F(DisplayTest, CompositorFrameWithMultipleRenderPass) {
RendererSettings settings; RendererSettings settings;
SetUpGpuDisplay(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