Commit 643c3e9a authored by Maggie Chen's avatar Maggie Chen Committed by Commit Bot

Optimize damage rect added from the previous overlay damage

This optimization reduces the damage rect size when the current damage rect
doesn't cover the video quad. For example, the video is paused or no video
change in this frame.

Because the overlay image is missing in gl composition, there might be
corruption if the old overlay needs to be redrawn in gl composition but the
damage rect doesn't cover it. Although sometimes it's needed to add the
overlay damage rect from the previous frame. It might increase the damage rect
than necessary when overlay is the same.

The unioned overlay quad size of the previous frame was always added to the
damage rect of the next frame before calling the overlay processor. This CL
optimizes the damage rect by handling the overlay damage rect in
DCLayerOverlayProcessor().

The other change of this CL is to move overlay and underlay validation code into
one function. This makes it easier to read and makes sure there is no validation
failures after the damage rect has changed.

BUG=868561

Change-Id: Ia66b950d5f010cb4b65288276cb9486e0d3d7709
Reviewed-on: https://chromium-review.googlesource.com/c/1472190
Commit-Queue: Maggie Chen <magchen@chromium.org>
Reviewed-by: default avatarSunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: default avatarZhenyao Mo <zmo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#634952}
parent 63406aee
......@@ -75,14 +75,15 @@ class DCLayerOverlayProcessor {
void Process(DisplayResourceProvider* resource_provider,
const gfx::RectF& display_rect,
RenderPassList* render_passes,
gfx::Rect* overlay_damage_rect,
gfx::Rect* damage_rect,
DCLayerOverlayList* dc_layer_overlays);
void ClearOverlayState() {
previous_frame_underlay_rect_ = gfx::Rect();
previous_frame_underlay_occlusion_ = gfx::Rect();
}
void ClearOverlayState();
void SetHasHwOverlaySupport() { has_hw_overlay_support_ = true; }
// This is the damage contribution due to previous frame's overlays which can
// be empty.
gfx::Rect previous_frame_overlay_damage_contribution() {
return previous_frame_overlay_rect_union_;
}
private:
// Returns an iterator to the element after |it|.
......@@ -94,16 +95,14 @@ class DCLayerOverlayProcessor {
const gfx::RectF& display_rect,
RenderPass* render_pass,
bool is_root,
gfx::Rect* overlay_damage_rect,
gfx::Rect* damage_rect,
DCLayerOverlayList* dc_layer_overlays);
bool ProcessForOverlay(const gfx::RectF& display_rect,
void ProcessForOverlay(const gfx::RectF& display_rect,
QuadList* quad_list,
const gfx::Rect& quad_rectangle,
const gfx::RectF& occlusion_bounding_box,
QuadList::Iterator* it,
gfx::Rect* damage_rect);
bool ProcessForUnderlay(const gfx::RectF& display_rect,
void ProcessForUnderlay(const gfx::RectF& display_rect,
RenderPass* render_pass,
const gfx::Rect& quad_rectangle,
const gfx::RectF& occlusion_bounding_box,
......@@ -118,7 +117,11 @@ class DCLayerOverlayProcessor {
gfx::Rect previous_frame_underlay_rect_;
gfx::Rect previous_frame_underlay_occlusion_;
gfx::RectF previous_display_rect_;
bool processed_overlay_in_frame_ = false;
// previous and current overlay_rect_union_ include both overlay and underlay
gfx::Rect previous_frame_overlay_rect_union_;
gfx::Rect current_frame_overlay_rect_union_;
int previous_frame_processed_overlay_count_ = 0;
int current_frame_processed_overlay_count_ = 0;
bool has_hw_overlay_support_ = true;
// Store information about clipped punch-through rects in target space for
......
......@@ -109,9 +109,9 @@ bool OverlayProcessor::ProcessForDCLayers(
if (!overlay_validator || !overlay_validator->AllowDCLayerOverlays())
return false;
dc_processor_.Process(
resource_provider, gfx::RectF(render_passes->back()->output_rect),
render_passes, &overlay_damage_rect_, damage_rect, dc_layer_overlays);
dc_processor_.Process(resource_provider,
gfx::RectF(render_passes->back()->output_rect),
render_passes, damage_rect, dc_layer_overlays);
DCHECK(overlay_candidates->empty());
return true;
......@@ -150,7 +150,12 @@ void OverlayProcessor::ProcessForOverlays(
// CALayers because the framebuffer would be missing the removed quads'
// contents.
if (!render_pass->copy_requests.empty()) {
damage_rect->Union(
dc_processor_.previous_frame_overlay_damage_contribution());
// Update damage rect before calling ClearOverlayState, otherwise
// previous_frame_overlay_rect_union will be empty.
dc_processor_.ClearOverlayState();
return;
}
......
......@@ -2455,7 +2455,89 @@ TEST_F(DCLayerOverlayTest, Occluded) {
// The underlay rectangle is the same, so the damage for first video quad is
// contained within the combined occluding rects for this and the last
// frame. Second video quad also adds its damage.
EXPECT_EQ(gfx::Rect(1, 2, 255, 254), damage_rect_);
// This is calculated by carving out the underlay rect size from the
// damage_rect, adding back the quads on top and then the overlay/underlay
// rects from the previous frame. The damage rect carried over from the
// revious frame with multiple overlays cannot be skipped.
EXPECT_EQ(gfx::Rect(0, 0, 256, 256), damage_rect_);
}
}
TEST_F(DCLayerOverlayTest, DamageRectWithoutVideoDamage) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(features::kDirectCompositionUnderlays);
{
std::unique_ptr<RenderPass> pass = CreateRenderPass();
// Occluding quad fully contained in video rect.
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
gfx::Rect(0, 3, 100, 100), SK_ColorWHITE);
// Non-occluding quad fully outside video rect
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
gfx::Rect(210, 210, 20, 20), SK_ColorWHITE);
// Underlay video quad
auto* video_quad = CreateFullscreenCandidateYUVVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
video_quad->rect = gfx::Rect(0, 0, 200, 200);
video_quad->visible_rect = video_quad->rect;
DCLayerOverlayList dc_layer_list;
OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
// Damage rect fully outside video quad
damage_rect_ = gfx::Rect(210, 210, 20, 20);
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_backdrop_filters, &overlay_list,
nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, dc_layer_list.size());
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
EXPECT_EQ(-1, dc_layer_list.back().z_order);
// All rects must be redrawn at the first frame.
EXPECT_EQ(gfx::Rect(0, 0, 230, 230), damage_rect_);
}
{
std::unique_ptr<RenderPass> pass = CreateRenderPass();
// Occluding quad fully contained in video rect.
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
gfx::Rect(0, 3, 100, 100), SK_ColorWHITE);
// Non-occluding quad fully outside video rect
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
gfx::Rect(210, 210, 20, 20), SK_ColorWHITE);
// Underlay video quad
auto* video_quad = CreateFullscreenCandidateYUVVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
video_quad->rect = gfx::Rect(0, 0, 200, 200);
video_quad->visible_rect = video_quad->rect;
DCLayerOverlayList dc_layer_list;
OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters;
// Damage rect fully outside video quad
damage_rect_ = gfx::Rect(210, 210, 20, 20);
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_backdrop_filters, &overlay_list,
nullptr, &dc_layer_list, &damage_rect_, &content_bounds_);
EXPECT_EQ(0U, overlay_list.size());
EXPECT_EQ(1U, dc_layer_list.size());
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
EXPECT_EQ(-1, dc_layer_list.back().z_order);
// Only the non-overlay damaged rect need to be drawn by the gl compositor
EXPECT_EQ(gfx::Rect(210, 210, 20, 20), damage_rect_);
}
}
......@@ -2584,8 +2666,10 @@ TEST_F(DCLayerOverlayTest, MultiplePassDamageRect) {
EXPECT_EQ(gfx::Rect(0, 0, 256, 256), pass_list[0]->damage_rect);
EXPECT_EQ(gfx::Rect(), pass_list[1]->damage_rect);
EXPECT_EQ(gfx::Rect(0, 100, 256, 156), root_damage_rect);
// Overlay damage handling is done entirely within DCOverlayProcessor so this
// is expected to return an empty rect
gfx::Rect overlay_damage = overlay_processor_->GetAndResetOverlayDamage();
EXPECT_EQ(gfx::Rect(0, 100, 256, 256), overlay_damage);
EXPECT_EQ(gfx::Rect(0, 0, 0, 0), overlay_damage);
EXPECT_EQ(1u, pass_list[0]->quad_list.size());
EXPECT_EQ(DrawQuad::SOLID_COLOR,
......
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