| // Copyright 2019 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_OVERLAY_PROCESSOR_USING_STRATEGY_H_ |
| #define COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_PROCESSOR_USING_STRATEGY_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <optional> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "base/hash/hash.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/time/time.h" |
| #include "build/build_config.h" |
| #include "components/viz/common/quads/aggregated_render_pass.h" |
| #include "components/viz/common/quads/quad_list.h" |
| #include "components/viz/service/display/aggregated_frame.h" |
| #include "components/viz/service/display/output_surface.h" |
| #include "components/viz/service/display/overlay_candidate.h" |
| #include "components/viz/service/display/overlay_candidate_temporal_tracker.h" |
| #include "components/viz/service/display/overlay_combination_cache.h" |
| #include "components/viz/service/display/overlay_processor_interface.h" |
| #include "components/viz/service/display/overlay_processor_strategy.h" |
| #include "components/viz/service/display/overlay_proposed_candidate.h" |
| #include "components/viz/service/viz_service_export.h" |
| #include "gpu/ipc/common/surface_handle.h" |
| #include "third_party/skia/include/core/SkM44.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/size.h" |
| #include "ui/gfx/overlay_transform.h" |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| // TODO(b/181974042): Remove when color space is plumbed. |
| #include "ui/gfx/color_space.h" |
| #endif // BUILDFLAG(IS_CHROMEOS) |
| |
| namespace viz { |
| |
| class DisplayResourceProvider; |
| |
| // OverlayProcessor subclass that goes through a list of strategies to determine |
| // overlay candidates. This is used by Android and Ozone platforms. |
| class VIZ_SERVICE_EXPORT OverlayProcessorUsingStrategy |
| : public OverlayProcessorInterface { |
| public: |
| using CandidateList = OverlayCandidateList; |
| // TODO(crbug.com/444264038): Delete this declaration when the RPDQ refactor |
| // is finished. Need to avoid hiding the base class' overload. |
| using OverlayProcessorInterface::ProcessForOverlays; |
| |
| OverlayProcessorUsingStrategy(const OverlayProcessorUsingStrategy&) = delete; |
| OverlayProcessorUsingStrategy& operator=( |
| const OverlayProcessorUsingStrategy&) = delete; |
| |
| ~OverlayProcessorUsingStrategy() override; |
| |
| gfx::Rect GetAndResetOverlayDamage() final; |
| |
| // Override OverlayProcessor. |
| void SetDisplayTransformHint(gfx::OverlayTransform transform) override {} |
| void SetViewportSize(const gfx::Size& size) override {} |
| void SetFrameSequenceNumber(uint64_t frame_sequence_number_) override; |
| // Attempts to replace quads from the specified root render pass with |
| // overlays. This must be called every frame. |
| void ProcessForOverlays( |
| DisplayResourceProvider* resource_provider, |
| AggregatedRenderPassList* render_passes, |
| const SkM44& output_color_matrix, |
| const FilterOperationsMap& render_pass_filters, |
| const FilterOperationsMap& render_pass_backdrop_filters, |
| SurfaceDamageRectList surface_damage_rect_list, |
| std::optional<OverlayCandidate>& primary_plane, |
| CandidateList* overlay_candidates, |
| gfx::Rect* damage_rect, |
| std::vector<gfx::Rect>* content_bounds) |
| // TODO(petermcneeley) : Restore to "final" once |
| // |OverlayProcessorDelegated| has been reintegrated into |
| // |OverlayProcessorOzone|. |
| override; |
| |
| OverlayProcessorUsingStrategy(); |
| |
| // A list of possible overlay candidates is presented to this function. |
| // The expected result is that those candidates that can be in a separate |
| // plane are marked with |overlay_handled| set to true, otherwise they are |
| // to be traditionally composited. Candidates with |overlay_handled| set to |
| // true must also have their |display_rect| converted to integer |
| // coordinates if necessary. |
| void CheckOverlaySupport(const std::optional<OverlayCandidate>& primary_plane, |
| OverlayCandidateList* candidate_list); |
| |
| // Clears the cache of attempted overlay combinations and their results. |
| void ClearOverlayCombinationCache(); |
| |
| // This should be called during overlay processing to register whether or not |
| // there is a candidate that requires an overlay so that the manager can allow |
| // the overlay on the display with the requirement only. |
| virtual void RegisterOverlayRequirement(bool requires_overlay) {} |
| |
| // Disable overlay if there has been a copy request in the last 10 frames |
| // 10 was chosen because worst case the copy request might be 15 fps and |
| // we might have display with 120 Hz. |
| static const int kCopyRequestSkipOverlayFrames = 10; |
| |
| const std::unordered_map<ProposedCandidateKey, |
| OverlayCandidateTemporalTracker, |
| ProposedCandidateKeyHasher>& |
| GetTrackedCandidatesForTesting() const { |
| return tracked_candidates_; |
| } |
| |
| protected: |
| virtual gfx::Rect GetOverlayDamageRectForOutputSurface( |
| const OverlayCandidate& overlay) const; |
| |
| virtual void InsertPrimaryPlane(OverlayCandidate primary_plane, |
| OverlayCandidateList& candidates); |
| |
| std::vector<std::unique_ptr<OverlayProcessorStrategy>> strategies_; |
| |
| // Only tracked when multi-overlay is not used. |
| raw_ptr<OverlayProcessorStrategy> last_successful_strategy_ = nullptr; |
| |
| gfx::Rect overlay_damage_rect_; |
| gfx::Rect previous_frame_overlay_rect_; |
| |
| struct OverlayPrioritizationConfig { |
| // Threshold criteria required for a proposed candidate to be considered for |
| // overlay promotion |
| bool changing_threshold = true; |
| bool damage_rate_threshold = true; |
| |
| // Sorting criteria that determines the relative order of consideration for |
| // a overlay candidate. |
| bool power_gain_sort = true; |
| }; |
| |
| OverlayPrioritizationConfig prioritization_config_; |
| OverlayCandidateTemporalTracker::Config tracker_config_; |
| |
| // This is controlled by the "UseMultipleOverlays" feature's "max_overlays" |
| // param. |
| const int max_overlays_config_; |
| // This will remain 1 until hardware support for more than one overlay is |
| // confirmed in `OverlayProcessorOzone::ReceiveHardwareCapabilities`. |
| int max_overlays_considered_ = 1; |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| protected: |
| // TODO(b/181974042): Remove when color space is plumbed. |
| gfx::ColorSpace primary_plane_color_space_; |
| #endif |
| |
| private: |
| // Keeps track of overlay information needed to update damage correctly. |
| struct OverlayStatus; |
| using OverlayStatusMap = std::map<gfx::Rect, OverlayStatus>; |
| |
| struct OverlayStatus { |
| OverlayStatus() = delete; |
| OverlayStatus(const OverlayCandidate& candidate, |
| const gfx::Rect& key, |
| const OverlayStatusMap& prev_overlays); |
| OverlayStatus(const OverlayStatus&); |
| OverlayStatus& operator=(const OverlayStatus&); |
| ~OverlayStatus(); |
| |
| gfx::Rect overlay_rect; |
| gfx::RectF damage_rect; |
| uint32_t damage_index; |
| float damage_area_estimate; |
| bool has_mask_filter; |
| int plane_z_order; |
| bool is_underlay; |
| bool is_opaque; |
| bool is_new; |
| bool prev_was_opaque; |
| bool prev_was_underlay; |
| bool prev_has_mask_filter; |
| }; |
| |
| // The platform specific implementation to check overlay support that will be |
| // called by `CheckOverlaySupport()`. |
| virtual void CheckOverlaySupportImpl( |
| const std::optional<OverlayCandidate>& primary_plane, |
| OverlayCandidateList* candidate_list) = 0; |
| |
| // Updates |damage_rect| by removing damage caused by overlays. |
| void UpdateDamageRect(const SurfaceDamageRectList& surface_damage_rect_list, |
| gfx::Rect& damage_rect); |
| gfx::Rect ComputeDamageExcludingOverlays( |
| const SurfaceDamageRectList& surface_damage_rect_list, |
| const gfx::Rect& existing_damage); |
| |
| // Iterates through a list of strategies and attempts to overlay with each. |
| // Returns true if one of the attempts is successful. Has to be called after |
| // InitializeStrategies(). A |primary_plane| represents the output surface's |
| // buffer that comes from |BufferQueue|. It is passed in here so it could be |
| // pass through to hardware through CheckOverlaySupport. It is not passed |
| // through as a const member because the underlay strategy changes the |
| // |primary_plane|'s blending setting. |
| bool AttemptWithStrategies( |
| const SkM44& output_color_matrix, |
| const OverlayProcessorInterface::FilterOperationsMap& render_pass_filters, |
| const OverlayProcessorInterface::FilterOperationsMap& |
| render_pass_backdrop_filters, |
| const DisplayResourceProvider* resource_provider, |
| AggregatedRenderPassList* render_pass_list, |
| SurfaceDamageRectList* surface_damage_rect_list, |
| std::optional<OverlayCandidate>& primary_plane, |
| OverlayCandidateList* candidates, |
| std::vector<gfx::Rect>* content_bounds, |
| gfx::Rect* incoming_damage); |
| |
| // Skips overlay when we have recently had copy output requests |
| // on root render pass to avoid flickering during screen capture |
| bool BlockForCopyRequests(const AggregatedRenderPass* root_render_pass); |
| |
| // Determines if we should attempt multiple overlays. This is based on |
| // `max_overlays_considered_`, the strategies proposed, and if any of the |
| // candidates require an overlay. |
| bool ShouldAttemptMultipleOverlays( |
| const std::vector<OverlayProposedCandidate>& sorted_candidates); |
| |
| // Attempts to promote multiple candidates to overlays. Returns a boolean |
| // indicating if any of the attempted candidates were successfully promoted to |
| // overlays. |
| // |
| // TODO(khaslett): Write unit tests for this function before launching |
| // UseMultipleOverlays feature. |
| bool AttemptMultipleOverlays( |
| const std::vector<OverlayProposedCandidate>& sorted_candidates, |
| std::optional<OverlayCandidate>& primary_plane, |
| AggregatedRenderPass* render_pass, |
| OverlayCandidateList& candidates); |
| |
| // Assigns `plane_z_order`s to the proposed underlay candidates based on their |
| // DrawQuad orderings. |
| // |
| // TODO(khaslett): Write unit tests for this function before launching |
| // UseMultipleOverlays feature. |
| void AssignUnderlayZOrders( |
| std::vector<std::vector<OverlayProposedCandidate>::iterator>& |
| underlay_iters); |
| |
| // This function reorders and removes |proposed_candidates| based on a |
| // heuristic designed to maximize the effectiveness of the limited number |
| // of Hardware overlays. Effectiveness here is primarily about power and |
| // secondarily about of performance. |
| virtual void SortProposedOverlayCandidates( |
| std::vector<OverlayProposedCandidate>* proposed_candidates); |
| |
| // Used by Android pre-SurfaceControl to notify promotion hints, and by |
| // Ozone to notify overlay manager what overlays are actually promoted. |
| virtual void NotifyOverlayPromotion( |
| DisplayResourceProvider* display_resource_provider, |
| const OverlayCandidateList& candidate_list, |
| const QuadList& quad_list); |
| |
| // Used to update |min_working_scale_| and |max_failed_scale_|. |scale_factor| |
| // should be the src->dst scaling amount that is < 1.0f and |success| should |
| // be whether that scaling worked or not. |
| void UpdateDownscalingCapabilities(float scale_factor, bool success); |
| |
| // Moves `curr_overlays` into `prev_overlays`, and updates `curr_overlays` to |
| // reflect the overlays that will be promoted this frame in `candidates`. |
| void UpdateOverlayStatusMap(const OverlayCandidateList& candidates); |
| |
| std::unordered_map<ProposedCandidateKey, |
| OverlayCandidateTemporalTracker, |
| ProposedCandidateKeyHasher> |
| tracked_candidates_; |
| |
| // These variables are used only for UMA purposes. |
| uint64_t frame_sequence_number_ = 0; |
| |
| // These values are used for tracking how much we can downscale with overlays |
| // and is used for when we require an overlay so we can determine how much we |
| // can downscale without failing. |
| float min_working_scale_ = 1.0f; |
| float max_failed_scale_ = 0.0f; |
| |
| // These keep track of the status of promoted overlays from one frame to the |
| // next. These maps are updated by calling UpdateOverlayStatusMap(), and are |
| // used by UpdateDamageRect() to update damage properly. |
| OverlayStatusMap prev_overlays_; |
| OverlayStatusMap curr_overlays_; |
| |
| OverlayCombinationCache overlay_combination_cache_; |
| |
| // Used to count the number of frames we should wait until enabling overlay |
| // again. |
| int copy_request_counter_ = 0; |
| }; |
| |
| } // namespace viz |
| |
| #endif // COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_PROCESSOR_USING_STRATEGY_H_ |