Commit df5b05da authored by Peter McNeeley's avatar Peter McNeeley Committed by Chromium LUCI CQ

Improved overlay strategy damage for specific contexts.

In the situation of there being damage above an overlay we currently do
not remove the damage of the underlay. A good example of where this
occurs is the timeline controls on top of a youtube video. So instead of
doing the smallest amount of damage (say for the seconds counter) we
damage the entire video display region. There are other contexts for
which the overlay damage region is not removed but in the end these all
come down to the difficulty of subtracting damage from the incoming root
damage.

In this change we move from subtracting overlay damage to excluding it
via the |SurfaceDamageList|. This results in much more accurate final
damage and thus improve power usage. This change also dramatically
reduces the complexity of previously error prone overlay damage
subtraction computations.

Finally, this change moves us closer to our goal of doing damage
extraction on a per quad level in surface aggregator.
See this document for more information:
 https://docs.google.com/document/d/
1yDnz1DKcSwfMZwmeRR_RRS3QznpzqLnsMeeYIk-ORfA/edit?usp=sharing



Change-Id: Ia5901546bd3982b8054b5ae9d0f397c22d7e5228
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2558918Reviewed-by: default avatarMaggie Chen <magchen@chromium.org>
Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Commit-Queue: Peter McNeeley <petermcneeley@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836164}
parent 76af7631
...@@ -26,6 +26,10 @@ ...@@ -26,6 +26,10 @@
namespace viz { namespace viz {
// There is a bug in |base::optional| which causes the 'value_or' function to
// capture parameters (even constexpr parameters) as a reference.
constexpr uint32_t OverlayCandidate::kInvalidDamageIndex;
namespace { namespace {
// Tolerance for considering axis vector elements to be zero. // Tolerance for considering axis vector elements to be zero.
const SkScalar kEpsilon = std::numeric_limits<float>::epsilon(); const SkScalar kEpsilon = std::numeric_limits<float>::epsilon();
...@@ -82,30 +86,6 @@ gfx::OverlayTransform GetOverlayTransform(const gfx::Transform& quad_transform, ...@@ -82,30 +86,6 @@ gfx::OverlayTransform GetOverlayTransform(const gfx::Transform& quad_transform,
return gfx::OVERLAY_TRANSFORM_INVALID; return gfx::OVERLAY_TRANSFORM_INVALID;
} }
bool HasOccludingDamage(const SharedQuadState* shared_quad_state,
SurfaceDamageRectList* surface_damage_rect_list) {
if (!shared_quad_state->overlay_damage_index.has_value())
return true;
size_t overlay_damage_index = shared_quad_state->overlay_damage_index.value();
// Invalid index.
if (overlay_damage_index >= surface_damage_rect_list->size()) {
DCHECK(false);
return true;
}
// Damage rects in surface_damage_rect_list are arranged from top to bottom.
// (*surface_damage_rect_list)[0] is the one on the very top.
// (*surface_damage_rect_list)[overlay_damage_index] is the damage rect of
// this overlay surface.
for (size_t i = 0; i < overlay_damage_index; ++i) {
if (!(*surface_damage_rect_list)[i].IsEmpty())
return true; // A damaged surface on top is found.
}
return false; // No occluding damages
}
gfx::Rect GetDamageRect(const DrawQuad* quad, gfx::Rect GetDamageRect(const DrawQuad* quad,
SurfaceDamageRectList* surface_damage_rect_list) { SurfaceDamageRectList* surface_damage_rect_list) {
const SharedQuadState* sqs = quad->shared_quad_state; const SharedQuadState* sqs = quad->shared_quad_state;
...@@ -147,13 +127,11 @@ OverlayCandidate::OverlayCandidate() ...@@ -147,13 +127,11 @@ OverlayCandidate::OverlayCandidate()
uv_rect(0.f, 0.f, 1.f, 1.f), uv_rect(0.f, 0.f, 1.f, 1.f),
is_clipped(false), is_clipped(false),
is_opaque(false), is_opaque(false),
no_occluding_damage(false),
resource_id(0), resource_id(0),
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
is_backed_by_surface_texture(false), is_backed_by_surface_texture(false),
is_promotable_hint(false), is_promotable_hint(false),
#endif #endif
is_unoccluded(false),
overlay_handled(false), overlay_handled(false),
gpu_fence_id(0) { gpu_fence_id(0) {
} }
...@@ -178,6 +156,11 @@ bool OverlayCandidate::FromDrawQuad( ...@@ -178,6 +156,11 @@ bool OverlayCandidate::FromDrawQuad(
// We don't support an opacity value different than one for an overlay plane. // We don't support an opacity value different than one for an overlay plane.
if (quad->shared_quad_state->opacity != 1.f) if (quad->shared_quad_state->opacity != 1.f)
return false; return false;
candidate->overlay_damage_index =
quad->shared_quad_state->overlay_damage_index.value_or(
kInvalidDamageIndex);
// We can't support overlays with mask filter. // We can't support overlays with mask filter.
if (!quad->shared_quad_state->mask_filter_info.IsEmpty()) if (!quad->shared_quad_state->mask_filter_info.IsEmpty())
return false; return false;
...@@ -340,8 +323,6 @@ bool OverlayCandidate::FromDrawQuadResource( ...@@ -340,8 +323,6 @@ bool OverlayCandidate::FromDrawQuadResource(
candidate->clip_rect = quad->shared_quad_state->clip_rect; candidate->clip_rect = quad->shared_quad_state->clip_rect;
candidate->is_clipped = quad->shared_quad_state->is_clipped; candidate->is_clipped = quad->shared_quad_state->is_clipped;
candidate->is_opaque = !quad->ShouldDrawWithBlending(); candidate->is_opaque = !quad->ShouldDrawWithBlending();
candidate->no_occluding_damage =
!HasOccludingDamage(quad->shared_quad_state, surface_damage_rect_list);
// For underlays the function 'EstimateVisibleDamage()' is called to update // For underlays the function 'EstimateVisibleDamage()' is called to update
// |damage_area_estimate| to more accurately reflect the actual visible // |damage_area_estimate| to more accurately reflect the actual visible
// damage. // damage.
...@@ -371,8 +352,6 @@ bool OverlayCandidate::FromVideoHoleQuad( ...@@ -371,8 +352,6 @@ bool OverlayCandidate::FromVideoHoleQuad(
candidate->display_rect = gfx::RectF(quad->rect); candidate->display_rect = gfx::RectF(quad->rect);
transform.TransformRect(&candidate->display_rect); transform.TransformRect(&candidate->display_rect);
candidate->transform = overlay_transform; candidate->transform = overlay_transform;
candidate->no_occluding_damage =
!HasOccludingDamage(quad->shared_quad_state, surface_damage_rect_list);
// For underlays the function 'EstimateVisibleDamage()' is called to update // For underlays the function 'EstimateVisibleDamage()' is called to update
// |damage_area_estimate| to more accurately reflect the actual visible // |damage_area_estimate| to more accurately reflect the actual visible
// damage. // damage.
......
...@@ -99,8 +99,6 @@ class VIZ_SERVICE_EXPORT OverlayCandidate { ...@@ -99,8 +99,6 @@ class VIZ_SERVICE_EXPORT OverlayCandidate {
bool is_clipped; bool is_clipped;
// If the quad doesn't require blending. // If the quad doesn't require blending.
bool is_opaque; bool is_opaque;
// The quad's occluding damage rect is empty.
bool no_occluding_damage;
// Texture resource to present in an overlay. // Texture resource to present in an overlay.
unsigned resource_id; unsigned resource_id;
// Mailbox from resource_id. It is used by SkiaRenderer. // Mailbox from resource_id. It is used by SkiaRenderer.
...@@ -121,11 +119,6 @@ class VIZ_SERVICE_EXPORT OverlayCandidate { ...@@ -121,11 +119,6 @@ class VIZ_SERVICE_EXPORT OverlayCandidate {
// which is 0. Signed to allow for "underlays". // which is 0. Signed to allow for "underlays".
int plane_z_order = 0; int plane_z_order = 0;
// True if the overlay does not have any visible quads on top of it. Set by
// the strategy so the OverlayProcessor can consider subtracting damage caused
// by underlay quads.
bool is_unoccluded;
// To be modified by the implementer if this candidate can go into // To be modified by the implementer if this candidate can go into
// an overlay. // an overlay.
bool overlay_handled; bool overlay_handled;
...@@ -138,6 +131,10 @@ class VIZ_SERVICE_EXPORT OverlayCandidate { ...@@ -138,6 +131,10 @@ class VIZ_SERVICE_EXPORT OverlayCandidate {
int damage_area_estimate = 0; int damage_area_estimate = 0;
// Result of call to 'RequiresOverlay' function w/ associated quad. // Result of call to 'RequiresOverlay' function w/ associated quad.
static constexpr uint32_t kInvalidDamageIndex = UINT_MAX;
uint32_t overlay_damage_index = kInvalidDamageIndex;
// Cached result of call to 'RequiresOverlay' function.
bool requires_overlay = false; bool requires_overlay = false;
private: private:
......
...@@ -170,8 +170,8 @@ class VIZ_SERVICE_EXPORT OverlayProcessorUsingStrategy ...@@ -170,8 +170,8 @@ class VIZ_SERVICE_EXPORT OverlayProcessorUsingStrategy
Strategy* last_successful_strategy_ = nullptr; Strategy* last_successful_strategy_ = nullptr;
gfx::Rect overlay_damage_rect_; gfx::Rect overlay_damage_rect_;
gfx::Rect previous_frame_underlay_rect_; bool previous_is_underlay = false;
bool previous_frame_underlay_was_unoccluded_ = false; gfx::Rect previous_frame_overlay_rect_;
struct OverlayPrioritizationConfig { struct OverlayPrioritizationConfig {
// Threshold criteria required for a proposed candidate to be considered for // Threshold criteria required for a proposed candidate to be considered for
...@@ -190,8 +190,7 @@ class VIZ_SERVICE_EXPORT OverlayProcessorUsingStrategy ...@@ -190,8 +190,7 @@ class VIZ_SERVICE_EXPORT OverlayProcessorUsingStrategy
private: private:
// Update |damage_rect| by removing damage caused by |candidates|. // Update |damage_rect| by removing damage caused by |candidates|.
void UpdateDamageRect(OverlayCandidateList* candidates, void UpdateDamageRect(OverlayCandidateList* candidates,
const gfx::Rect& previous_frame_underlay_rect, SurfaceDamageRectList* surface_damage_rect_list,
bool previous_frame_underlay_was_unoccluded,
const QuadList* quad_list, const QuadList* quad_list,
gfx::Rect* damage_rect); gfx::Rect* damage_rect);
......
...@@ -77,12 +77,8 @@ bool OverlayStrategyUnderlay::Attempt( ...@@ -77,12 +77,8 @@ bool OverlayStrategyUnderlay::Attempt(
// If the candidate can be handled by an overlay, create a pass for it. We // If the candidate can be handled by an overlay, create a pass for it. We
// need to switch out the video quad with a black transparent one. // need to switch out the video quad with a black transparent one.
if (new_candidate_list.back().overlay_handled) { if (new_candidate_list.back().overlay_handled) {
new_candidate_list.back().is_unoccluded =
!OverlayCandidate::IsOccluded(candidate, quad_list.cbegin(), it);
render_pass->ReplaceExistingQuadWithOpaqueTransparentSolidColor(it); render_pass->ReplaceExistingQuadWithOpaqueTransparentSolidColor(it);
candidate_list->swap(new_candidate_list); candidate_list->swap(new_candidate_list);
return true; return true;
} }
} }
...@@ -146,7 +142,7 @@ bool OverlayStrategyUnderlay::AttemptPrioritized( ...@@ -146,7 +142,7 @@ bool OverlayStrategyUnderlay::AttemptPrioritized(
// Before we attempt an overlay strategy, the candidate list should be empty. // Before we attempt an overlay strategy, the candidate list should be empty.
DCHECK(candidate_list->empty()); DCHECK(candidate_list->empty());
auto* render_pass = render_pass_list->back().get(); auto* render_pass = render_pass_list->back().get();
QuadList& quad_list = render_pass->quad_list;
// Add the overlay. // Add the overlay.
OverlayCandidateList new_candidate_list = *candidate_list; OverlayCandidateList new_candidate_list = *candidate_list;
new_candidate_list.push_back(proposed_candidate->candidate); new_candidate_list.push_back(proposed_candidate->candidate);
...@@ -170,10 +166,6 @@ bool OverlayStrategyUnderlay::AttemptPrioritized( ...@@ -170,10 +166,6 @@ bool OverlayStrategyUnderlay::AttemptPrioritized(
// If the candidate can be handled by an overlay, create a pass for it. We // If the candidate can be handled by an overlay, create a pass for it. We
// need to switch out the video quad with a black transparent one. // need to switch out the video quad with a black transparent one.
if (new_candidate_list.back().overlay_handled) { if (new_candidate_list.back().overlay_handled) {
new_candidate_list.back().is_unoccluded = !OverlayCandidate::IsOccluded(
proposed_candidate->candidate, quad_list.cbegin(),
proposed_candidate->quad_iter);
render_pass->ReplaceExistingQuadWithOpaqueTransparentSolidColor( render_pass->ReplaceExistingQuadWithOpaqueTransparentSolidColor(
proposed_candidate->quad_iter); proposed_candidate->quad_iter);
candidate_list->swap(new_candidate_list); candidate_list->swap(new_candidate_list);
......
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