blob: 620074bc535450194c0d174cb1356c8e3c6798de [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/viz/service/display/overlay_strategy_underlay.h"
#include <vector>
#include "components/viz/common/quads/aggregated_render_pass.h"
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/overlay_candidate_factory.h"
namespace viz {
OverlayStrategyUnderlay::OverlayStrategyUnderlay(
OverlayProcessorUsingStrategy* capability_checker,
OpaqueMode opaque_mode)
: capability_checker_(capability_checker), opaque_mode_(opaque_mode) {
DCHECK(capability_checker);
}
OverlayStrategyUnderlay::~OverlayStrategyUnderlay() {}
void OverlayStrategyUnderlay::Propose(
const SkM44& output_color_matrix,
const OverlayProcessorInterface::FilterOperationsMap& render_pass_filters,
const OverlayProcessorInterface::FilterOperationsMap&
render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
AggregatedRenderPassList* render_pass_list,
SurfaceDamageRectList* surface_damage_rect_list,
const PrimaryPlane* primary_plane,
std::vector<OverlayProposedCandidate>* candidates,
std::vector<gfx::Rect>* content_bounds) {
auto* render_pass = render_pass_list->back().get();
QuadList& quad_list = render_pass->quad_list;
OverlayCandidateFactory candidate_factory = OverlayCandidateFactory(
render_pass, resource_provider, surface_damage_rect_list,
&output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane),
&render_pass_filters);
for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
OverlayCandidate candidate;
if (candidate_factory.FromDrawQuad(*it, candidate) !=
OverlayCandidate::CandidateStatus::kSuccess ||
(opaque_mode_ == OpaqueMode::RequireOpaqueCandidates &&
!candidate.is_opaque)) {
continue;
}
// Filters read back the framebuffer to get the pixel values that need to
// be filtered. This is a problem when there are hardware planes because
// the planes are not composited until they are on the display controller.
// If we are requiring an overlay, then we should not block it due to this
// condition.
if (!candidate.requires_overlay &&
candidate_factory.IsOccludedByFilteredQuad(
candidate, quad_list.begin(), it, render_pass_backdrop_filters)) {
continue;
}
candidate.damage_area_estimate = candidate_factory.EstimateVisibleDamage(
*it, candidate, quad_list.begin(), it);
candidates->push_back({it, candidate, this});
}
}
bool OverlayStrategyUnderlay::Attempt(
const SkM44& output_color_matrix,
const OverlayProcessorInterface::FilterOperationsMap& render_pass_filters,
const OverlayProcessorInterface::FilterOperationsMap&
render_pass_backdrop_filters,
DisplayResourceProvider* resource_provider,
AggregatedRenderPassList* render_pass_list,
SurfaceDamageRectList* surface_damage_rect_list,
const PrimaryPlane* primary_plane,
OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds,
const OverlayProposedCandidate& proposed_candidate) {
// Before we attempt an overlay strategy, the candidate list should be empty.
DCHECK(candidate_list->empty());
auto* render_pass = render_pass_list->back().get();
// Add the overlay.
OverlayCandidateList new_candidate_list = *candidate_list;
new_candidate_list.push_back(proposed_candidate.candidate);
new_candidate_list.back().plane_z_order = -1;
if (primary_plane) {
// Since there is a list of strategies to go through, each strategy should
// not change the input parameters. In this case, we need to keep the
// |primary_plane| unchanged. The underlay strategy only works when the
// |primary_plane| supports blending. In order to check the hardware
// support, make a copy of the |primary_plane| with blending enabled.
PrimaryPlane new_plane_candidate(*primary_plane);
new_plane_candidate.enable_blending = true;
// Check for support.
capability_checker_->CheckOverlaySupport(&new_plane_candidate,
&new_candidate_list);
} else {
capability_checker_->CheckOverlaySupport(nullptr, &new_candidate_list);
}
if (new_candidate_list.back().overlay_handled) {
CommitCandidate(proposed_candidate, render_pass);
candidate_list->swap(new_candidate_list);
return true;
}
return false;
}
void OverlayStrategyUnderlay::CommitCandidate(
const OverlayProposedCandidate& proposed_candidate,
AggregatedRenderPass* render_pass) {
// If the candidate can be handled by an overlay, create a pass for it. We
// need to switch out the video quad with an underlay hole quad.
if (proposed_candidate.candidate.has_mask_filter) {
render_pass->ReplaceExistingQuadWithSolidColor(
proposed_candidate.quad_iter, SkColors::kBlack, SkBlendMode::kDstOut);
} else {
render_pass->ReplaceExistingQuadWithSolidColor(proposed_candidate.quad_iter,
SkColors::kTransparent,
SkBlendMode::kSrcOver);
}
}
// Turn on blending for the output surface plane so the underlay could show
// through.
void OverlayStrategyUnderlay::AdjustOutputSurfaceOverlay(
OverlayProcessorInterface::OutputSurfaceOverlayPlane*
output_surface_plane) {
if (output_surface_plane)
output_surface_plane->enable_blending = true;
}
OverlayStrategy OverlayStrategyUnderlay::GetUMAEnum() const {
return OverlayStrategy::kUnderlay;
}
} // namespace viz