1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_DC_LAYER_OVERLAY_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_DC_LAYER_OVERLAY_H_
#include <vector>
#include "base/check_is_test.h"
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/power_monitor/power_monitor.h"
#include "base/threading/thread_checker.h"
#include "components/viz/common/quads/aggregated_render_pass.h"
#include "components/viz/service/display/aggregated_frame.h"
#include "components/viz/service/display/overlay_candidate.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/hdr_metadata.h"
#include "ui/gfx/video_types.h"
#include "ui/gl/direct_composition_support.h"
namespace viz {
class DisplayResourceProvider;
class VIZ_SERVICE_EXPORT DCLayerOverlayProcessor final
: public gl::DirectCompositionOverlayCapsObserver,
public base::PowerStateObserver {
public:
using FilterOperationsMap =
base::flat_map<AggregatedRenderPassId,
raw_ptr<cc::FilterOperations, CtnExperimental>>;
// When |skip_initialization_for_testing| is true, object will be isolated
// for unit tests.
explicit DCLayerOverlayProcessor(
int allowed_yuv_overlay_count,
bool disable_video_overlay_if_moving,
bool skip_initialization_for_testing = false);
DCLayerOverlayProcessor(const DCLayerOverlayProcessor&) = delete;
DCLayerOverlayProcessor& operator=(const DCLayerOverlayProcessor&) = delete;
~DCLayerOverlayProcessor() override;
// Encapsulates all of the information about a render pass's overlays that
// are returned back to OverlayProcessorWin. This is passed to Process() as an
// in/out parameter.
struct VIZ_SERVICE_EXPORT RenderPassOverlayData {
RenderPassOverlayData();
~RenderPassOverlayData();
RenderPassOverlayData(RenderPassOverlayData&&);
RenderPassOverlayData& operator=(RenderPassOverlayData&&);
// Damage rect of the render pass. Set by OverlayProcessorWin and may be
// optimized in UpdateDamageRect() if overlays are promoted.
gfx::Rect damage_rect;
// List of overlays that are actually promoted. Only used for output back to
// OverlayProcessorWin. Contains all the information necessary to draw the
// overlay quads in SkiaRenderer.
OverlayCandidateList promoted_overlays;
};
using RenderPassOverlayDataMap =
base::flat_map<raw_ptr<AggregatedRenderPass>, RenderPassOverlayData>;
// All render passes that should be considered for
// overlays in this frame should be in |render_pass_overlay_data_map|. After
// this function executes, |render_pass_overlay_data_map[render_pass]| will
// contain the all of the overlays promoted for |render_pass|. The z-order
// of the overlays are assigned relative to other overlays within the render
// pass, with positive z-orders being overlays and negative z-orders being
// underlays. The caller must aggregate overlays from all render passes into
// a global overlay list, taking into account the render pass's z-order.
void Process(
const DisplayResourceProvider* resource_provider,
const FilterOperationsMap& render_pass_filters,
const FilterOperationsMap& render_pass_backdrop_filters,
const SurfaceDamageRectList& surface_damage_rect_list_in_root_space,
bool is_page_fullscreen_mode,
RenderPassOverlayDataMap& render_pass_overlay_data_map);
// DirectCompositionOverlayCapsObserver implementation.
void OnOverlayCapsChanged() override;
// base::PowerStateObserver implementation.
void OnBatteryPowerStatusChange(
PowerStateObserver::BatteryPowerStatus battery_power_status) override;
void UpdateHasHwOverlaySupport();
void UpdateSystemHDRStatus();
void UpdateP010VideoProcessorSupport();
void UpdateAutoHDRVideoProcessorSupport();
void set_frames_since_last_qualified_multi_overlays_for_testing(int value) {
frames_since_last_qualified_multi_overlays_ = value;
}
void set_system_hdr_enabled_on_any_display_for_testing(bool value) {
system_hdr_enabled_on_any_display_ = value;
}
void set_system_hdr_disabled_on_any_display_for_testing(bool value) {
system_hdr_disabled_on_any_display_ = value;
}
void set_has_p010_video_processor_support_for_testing(bool value) {
has_p010_video_processor_support_ = value;
}
void set_has_auto_hdr_video_processor_support_for_testing(bool value) {
has_auto_hdr_video_processor_support_ = value;
}
void set_is_on_battery_power_for_testing(bool value) {
is_on_battery_power_ = value;
}
void set_disable_video_overlay_if_moving_for_testing(bool value) {
disable_video_overlay_if_moving_ = value;
}
bool force_overlay_for_auto_hdr() {
return system_hdr_enabled_on_any_display_ &&
has_auto_hdr_video_processor_support_ && !is_on_battery_power_;
}
size_t get_previous_frame_render_pass_count() const {
CHECK_IS_TEST();
return previous_frame_render_pass_states_.size();
}
std::vector<AggregatedRenderPassId> get_previous_frame_render_pass_ids()
const {
std::vector<AggregatedRenderPassId> ids;
for (const auto& [id, _] : previous_frame_render_pass_states_) {
ids.push_back(id);
}
return ids;
}
// This struct only contains minimal information about the overlays, enough to
// perform damage optimizations across frames.
struct OverlayRect {
gfx::Rect rect;
bool is_overlay = true; // If false, it's an underlay.
friend bool operator==(const OverlayRect&, const OverlayRect&) = default;
};
// Returns true if the `quad_below` meets the criteria to allow the quad above
// it to utilize the fullscreen letterboxing optimization in `DCLayerTree`.
// - `quad_below` must be the quad directly below the quad we are marking as
// "possible fullscreen letterboxing". If null, indicates there is nothing
// below the quad we're checking.
// - `display_rect` is ideally the monitor rect, but is approximated with the
// root render pass output rect.
// See implementation for details.
static bool IsPossibleFullScreenLetterboxing(const DrawQuad* quad_below,
const gfx::Rect& display_rect);
private:
// Information about a render pass's overlays from the previous frame. The
// previous frame's overlays are used for optimizations, which are done
// independently for each render pass. These optimizations try to remove
// render pass packing damage if the overlays are not changed between frames,
// which potentially allows us to skip drawing the render pass. We also add
// damage from overlays in the previous frame in the scenarios where we skip
// overlays in the current frame or if the overlays have changed. This damage
// needs to be re-added because the content under the overlays from the
// previous frame are likely out of date if they were optimized out.
struct RenderPassPreviousFrameState {
RenderPassPreviousFrameState();
~RenderPassPreviousFrameState();
RenderPassPreviousFrameState(RenderPassPreviousFrameState&&);
RenderPassPreviousFrameState& operator=(
RenderPassPreviousFrameState&& other);
// Whether the render pass had any promoted underlay quads that were opaque
// in the previous frame.
bool underlay_is_opaque = true;
// The output rect of the render pass in the previous frame.
gfx::Rect display_rect;
// Rects of all overlay and underlay quads that were promoted in the
// previous frame.
std::vector<OverlayRect> overlay_rects;
};
// Information about a render pass's overlays in the current frame being
// processed. This struct primarily serves to encapsulate all parameters
// relating to a render pass into one object that can be passed between
// multiple functions. These objects do not persist after this current frame
// is processed. While RenderPassOverlayData stores information that are
// exposed and returned to OverlayProcessorWin, this struct contains data used
// only internally to this class.
struct RenderPassCurrentFrameState {
RenderPassCurrentFrameState();
~RenderPassCurrentFrameState();
RenderPassCurrentFrameState(RenderPassCurrentFrameState&&);
RenderPassCurrentFrameState& operator=(RenderPassCurrentFrameState&& other);
// The surface damage rect list for the frame, in *render pass space*.
SurfaceDamageRectList surface_damage_rect_list;
// Overlay quad candidates in the render pass's quad list. These are
// overlays that have been identified as potential candidates for promotion
// and are collected in the initial stage of processing. Some or all of
// these candidates may or may not be actually promoted. We're storing
// iterators instead of the actual quad because some functions such as
// IsPossiblefullScreenLetterboxing and ProcessForUnderlay require knowing
// the position of the quad in the quad list.
std::vector<QuadList::Iterator> candidates;
// Rects of overlays that have been processed and successfully promoted and
// added to |RenderPassOverlayData::promoted_overlays|.
std::vector<OverlayRect> overlay_rects;
// Overlay damages that can be removed from the render pass's damage rect
// at the end of processing overlays. This vector stores indices of damages
// in |surface_damage_rect_list| that can be removed.
std::vector<size_t> damages_to_be_removed;
};
using RenderPassCurrentFrameStateMap =
base::flat_map<raw_ptr<AggregatedRenderPass>,
RenderPassCurrentFrameState>;
// Information about overlays in the current frame being processed. Unlike
// fields in RenderPassCurrentFrameState, these fields are not specific to any
// render pass. They are global to the entire frame. Similarly, this struct
// exists primarily to encapsulate variables into one object to pass between
// functions.
struct GlobalOverlayState {
// Actual number of yuv quads that are successfully processed and added as
// an overlay. Used to determine whether overlay should be skipped.
int processed_yuv_overlay_count = 0;
// Total number of yuv quads.
int yuv_quads = 0;
// Number of yuv quads that were considered for overlay promotion and have a
// non-empty surface damage.
int damaged_yuv_quads = 0;
// Tracks whether we have anything other than clear video overlays e.g. low
// latency canvas or protected video which are allowed for multiple
// overlays.
bool has_non_clear_video_overlays = false;
// Used for recording overlay histograms.
bool has_occluding_damage_rect = false;
// Whether to reject all overlays for this frame. This can be true if we
// have more than one overlay quad and not all of them are promoted to
// overlays.
bool reject_overlays = false;
};
// Collects the overlay candidates for a render pass. Coordinate systems for
// all parameters should be in render pass space.
//
// If video capture is enabled, overlays are not processed. In this case, the
// render pass's previous frame data is erased since there will be no overlays
// in the current frame.
//
// This function adds overlay candidates for |render_pass| into
// |render_pass_state| and accumulates information about |render_pass|
// into |global_overlay_state|. If overlays should be skipped for this
// render pass, the damage rect in |overlay_data| is unioned with the previous
// frame's overlay damages, and the previous frame state is cleared.
void CollectCandidates(
const DisplayResourceProvider* resource_provider,
AggregatedRenderPass* render_pass,
const FilterOperationsMap& render_pass_backdrop_filters,
RenderPassOverlayData& overlay_data,
RenderPassCurrentFrameState& render_pass_state,
GlobalOverlayState& global_overlay_state);
// Promotes overlay candidates for a render pass. Coordinate systems for all
// parameters should be in in render pass space.
//
// The render pass's corresponding RenderPassPreviousFrameState object in
// |previous_frame_overlay_candidate_rects_| is updated to contain this
// frame's data.
//
// This function adds overlays that have been promoted into |overlay_data|
// and accumulates their rects into the damage rect. It also updates all of
// |current_frame_state|'s fields and |processed_yuv_overlay_count| to reflect
// the actual number of overlays promoted.
void PromoteCandidates(
const DisplayResourceProvider* resource_provider,
AggregatedRenderPass* render_pass,
const FilterOperationsMap& render_pass_filters,
const RenderPassPreviousFrameState& previous_frame_state,
bool is_page_fullscreen_mode,
RenderPassOverlayData& overlay_data,
RenderPassCurrentFrameState& current_frame_state,
GlobalOverlayState& global_overlay_state);
// Detects overlay processing skip inside |render_pass|.
bool ShouldSkipOverlay(AggregatedRenderPass* render_pass) const;
// Creates an OverlayCandidate for a quad candidate and updates the states
// for the render pass.
void UpdateDCLayerOverlays(
const DisplayResourceProvider* resource_provider,
AggregatedRenderPass* render_pass,
const QuadList::Iterator& it,
const gfx::Rect& quad_rectangle_in_target_space,
const RenderPassPreviousFrameState& previous_frame_state,
bool is_overlay,
bool is_page_fullscreen_mode,
RenderPassOverlayData& overlay_data,
RenderPassCurrentFrameState& current_frame_state,
GlobalOverlayState& global_overlay_state);
void ProcessForOverlay(
AggregatedRenderPass* render_pass,
const QuadList::Iterator& it,
const RenderPassPreviousFrameState& previous_frame_state,
RenderPassCurrentFrameState& current_frame_state) const;
void ProcessForUnderlay(
AggregatedRenderPass* render_pass,
const QuadList::Iterator& it,
const gfx::Rect& quad_rectangle_in_target_space,
const RenderPassPreviousFrameState& previous_frame_state,
const GlobalOverlayState& global_overlay_state,
RenderPassOverlayData& overlay_data,
RenderPassCurrentFrameState& current_frame_state);
void UpdateDamageRect(
AggregatedRenderPass* render_pass,
const RenderPassPreviousFrameState& previous_frame_state,
RenderPassOverlayData& overlay_data,
RenderPassCurrentFrameState& current_frame_state) const;
void RemoveOverlayDamageRect(
const DrawQuad* quad,
RenderPassCurrentFrameState& render_pass_state) const;
// Remove all video overlay candidates if any overlays in any render passes
// have moved in the last several frames.
//
// We do this because it could cause visible stuttering of playback on certain
// older hardware. The stuttering does not occur if other overlay quads move
// while a non-moving video is playing.
//
// This only tracks clear video quads because hardware-protected videos cannot
// be accessed by the viz compositor, so they must be promoted to overlay,
// even if they could cause stutter. Software-protected video aren't required
// to be in overlay, but we also exclude them from de-promotion to keep the
// protection benefits of being in an overlay.
void RemoveClearVideoQuadCandidatesIfMoving(
const DisplayResourceProvider* resource_provider,
RenderPassOverlayDataMap& render_pass_overlay_data_map,
RenderPassCurrentFrameStateMap& render_pass_current_state_map);
bool has_overlay_support_;
bool has_p010_video_processor_support_ = false;
bool has_auto_hdr_video_processor_support_ = false;
// At least one monitor that has system HDR enabled.
bool system_hdr_enabled_on_any_display_ = false;
// At least one monitor that has system HDR disabled or doesn't support HDR.
bool system_hdr_disabled_on_any_display_ = true;
const int allowed_yuv_overlay_count_;
uint64_t frames_since_last_qualified_multi_overlays_ = 0;
bool allow_promotion_hinting_ = false;
bool is_on_battery_power_ = false;
// Information about overlays from the previous frame.
base::flat_map<AggregatedRenderPassId, RenderPassPreviousFrameState>
previous_frame_render_pass_states_;
// Used in `RemoveClearVideoQuadCandidatesIfMoving`
// List of clear video content candidate bounds. These rects are in root space
// and contains the candidate rects for all render passes.
// TODO(crbug.com/40272272): Compute these values using
// |previous_frame_render_pass_states_| and remove this field.
std::vector<gfx::Rect> previous_frame_overlay_candidate_rects_;
int frames_since_last_overlay_candidate_rects_change_ = 0;
bool no_undamaged_overlay_promotion_;
bool disable_video_overlay_if_moving_;
THREAD_CHECKER(thread_checker_);
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_DC_LAYER_OVERLAY_H_
|