chromium/components/viz/service/display/overlay_processor_win.h

// 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.

#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_PROCESSOR_WIN_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_PROCESSOR_WIN_H_

#include <memory>
#include <utility>
#include <vector>

#include "base/check_is_test.h"
#include "base/memory/raw_ptr.h"
#include "build/build_config.h"
#include "components/viz/common/quads/aggregated_render_pass.h"
#include "components/viz/service/display/dc_layer_overlay.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/overlay_candidate.h"
#include "components/viz/service/display/overlay_processor_delegated_support.h"
#include "components/viz/service/display/overlay_processor_interface.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/ipc/common/surface_handle.h"

namespace viz {
class DisplayResourceProvider;
struct DebugRendererSettings;
class OverlayCandidateFactory;

class VIZ_SERVICE_EXPORT OverlayProcessorWin
    : public OverlayProcessorInterface {
 public:
  OverlayProcessorWin(
      OutputSurface::DCSupportLevel dc_support_level,
      const DebugRendererSettings* debug_settings,
      std::unique_ptr<DCLayerOverlayProcessor> dc_layer_overlay_processor);

  OverlayProcessorWin(const OverlayProcessorWin&) = delete;
  OverlayProcessorWin& operator=(const OverlayProcessorWin&) = delete;

  ~OverlayProcessorWin() override;

  bool IsOverlaySupported() const override;
  gfx::Rect GetPreviousFrameOverlaysBoundingRect() const override;
  gfx::Rect GetAndResetOverlayDamage() override;

  // Returns true if the platform supports hw overlays and surface occluding
  // damage rect needs to be computed since it will be used by overlay
  // processor.
  bool NeedsSurfaceDamageRectList() const override;

  // Sets |is_page_fullscreen_mode_|.
  void SetIsPageFullscreen(bool enabled) override;

  void AdjustOutputSurfaceOverlay(
      std::optional<OutputSurfaceOverlayPlane>* output_surface_plane) override;

  // Attempt to replace quads from the specified root render pass with overlays
  // or CALayers. 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_in_root_space,
      OutputSurfaceOverlayPlane* output_surface_plane,
      OverlayCandidateList* overlay_candidates,
      gfx::Rect* root_damage_rect,
      std::vector<gfx::Rect>* content_bounds) override;

  void SetFrameHasDelegatedInk() override;

  bool frame_has_delegated_ink_for_testing() const {
    CHECK_IS_TEST();
    return frame_has_delegated_ink_;
  }

  // Sets whether or not |render_pass_id| will be marked for a DComp surface
  // backing. If |value| is true, this also resets the frame count since
  // enabling DC layers.
  void SetUsingDCLayersForTesting(AggregatedRenderPassId render_pass_id,
                                  bool value);

  static gfx::Rect InsertSurfaceContentOverlaysAndSetPlaneZOrderForTesting(
      DCLayerOverlayProcessor::RenderPassOverlayDataMap
          surface_content_render_passes,
      OverlayCandidateList& candidates);

 protected:
  // For testing.
  DCLayerOverlayProcessor* GetOverlayProcessor() {
    return dc_layer_overlay_processor_.get();
  }

 private:
  void InsertDebugBorderDrawQuadsForOverlayCandidates(
      const OverlayCandidateList& dc_layer_overlays,
      AggregatedRenderPass* render_pass,
      gfx::Rect& damage_rect);

  // Promote a subset of quads from the root render pass using
  // |DCLayerOverlayProcessor| while still intending to schedule the primary
  // plane as its own overlay. This is the fallback for delegated compositing
  // that still allows quads to be promoted e.g. for protected content or for
  // performance reasons.
  void ProcessOverlaysFromOutputSurfacePlane(
      DisplayResourceProvider* resource_provider,
      AggregatedRenderPassList* render_passes,
      const SkM44& output_color_matrix,
      const OverlayProcessorInterface::FilterOperationsMap& render_pass_filters,
      const OverlayProcessorInterface::FilterOperationsMap&
          render_pass_backdrop_filters,
      const SurfaceDamageRectList& surface_damage_rect_list_in_root_space,
      OutputSurfaceOverlayPlane* output_surface_plane,
      CandidateList* candidates,
      gfx::Rect* root_damage_rect);

  // Try to promote all quads from the root render pass to overlay.
  // In partially delegated compositing, RPDQs that represent surfaces will have
  // quads promoted from their render passes using |DCLayerOverlayProcessor|.
  DelegationStatus ProcessOverlaysForDelegation(
      DisplayResourceProvider* resource_provider,
      AggregatedRenderPassList* render_passes,
      const SkM44& output_color_matrix,
      const OverlayProcessorInterface::FilterOperationsMap& render_pass_filters,
      const OverlayProcessorInterface::FilterOperationsMap&
          render_pass_backdrop_filters,
      const SurfaceDamageRectList& surface_damage_rect_list_in_root_space,
      CandidateList* candidates,
      gfx::Rect* root_damage_rect);

  // This struct holds information about the RPDQ overlays promoted during
  // delegated compositing. It references objects in the current frame and is
  // only valid while the render pass list's pointers are valid.
  // TODO(crbug.com/324460866): Used for partially delegated compositing.
  struct PromotedRenderPassesInfo {
    PromotedRenderPassesInfo();
    ~PromotedRenderPassesInfo();

    PromotedRenderPassesInfo(PromotedRenderPassesInfo&&);
    PromotedRenderPassesInfo& operator=(PromotedRenderPassesInfo&&);

    // List of render passes that were embedded by a promoted RPDQ overlay.
    base::flat_set<raw_ref<AggregatedRenderPass>> promoted_render_passes;
    // List of RPDQs that were promoted to overlay.
    std::vector<raw_ref<const AggregatedRenderPassDrawQuad>> promoted_rpdqs;
  };

  // Result of attempting delegated compositing.
  struct DelegatedCompositingResult {
    DelegatedCompositingResult();
    ~DelegatedCompositingResult();

    DelegatedCompositingResult(DelegatedCompositingResult&&);
    DelegatedCompositingResult& operator=(DelegatedCompositingResult&&);

    OverlayCandidateList candidates;
    PromotedRenderPassesInfo promoted_render_passes_info;
  };

  // Attempt to promote all the quads in |root_render_pass|. Promoted quads will
  // be placed in |out_candidates| in front-to-back order. Returns true if all
  // quads were successfully promoted.
  base::expected<DelegatedCompositingResult, DelegationStatus>
  TryDelegatedCompositing(
      bool is_full_delegated_compositing,
      const AggregatedRenderPassList& render_passes,
      const OverlayCandidateFactory& factory,
      const OverlayProcessorInterface::FilterOperationsMap&
          render_pass_backdrop_filters,
      const DisplayResourceProvider* resource_provider) const;

  // Modifies the properties of |promoted_render_passes| for passes that are
  // referenced by RPDQ overlays. This gives |SkiaRenderer| enough information
  // to decide whether or not a RPDQ overlay can skip the copy in
  // |PrepareRenderPassOverlay| and, if so, whether to allocate a swap chain or
  // DComp surface backing. Returns the set of surfaces we should use
  // |DCLayerOverlayProcessor| to promote overlays from.
  // TODO(crbug.com/324460866): Used for partially delegated compositing.
  static DCLayerOverlayProcessor::RenderPassOverlayDataMap
  UpdatePromotedRenderPassPropertiesAndGetSurfaceContentPasses(
      bool is_full_delegated_compositing,
      const AggregatedRenderPassList& render_passes,
      const PromotedRenderPassesInfo& promoted_render_passes_info);

  // Insert overlay candidates from |surface_content_render_passes| into
  // |candidates|, assigning correct plane z-order in the process. |candidates|
  // is assumed to be in front-to-back. The resulting candidates list is not
  // sorted. Returns the union rect of overlays in
  // |surface_content_render_passes|.
  // TODO(crbug.com/324460866): Used for partially delegated compositing.
  static gfx::Rect InsertSurfaceContentOverlaysAndSetPlaneZOrder(
      DCLayerOverlayProcessor::RenderPassOverlayDataMap
          surface_content_render_passes,
      OverlayCandidateList& candidates);

  const OutputSurface::DCSupportLevel dc_support_level_;

  // Reference to the global viz singleton.
  const raw_ptr<const DebugRendererSettings> debug_settings_;

  // Number of frames since the last time direct composition layers were used
  // for each render pass we promote overlays from in the frame. Presence in
  // this map indicates that the render pass is using a DComp surface.
  base::flat_map<AggregatedRenderPassId, int> frames_since_using_dc_layers_map_;

  // TODO(weiliangc): Eventually fold DCLayerOverlayProcessor into this class.
  std::unique_ptr<DCLayerOverlayProcessor> dc_layer_overlay_processor_;

  bool is_page_fullscreen_mode_ = false;

  bool delegation_succeeded_last_frame_ = false;

  // If true, causes the use of DComp surfaces as the backing image of a render
  // pass, given that UseDCompSurfacesForDelegatedInk is also enabled.
  bool frame_has_delegated_ink_ = false;

  // Returned and reset by |GetAndResetOverlayDamage| to fully damage the root
  // render pass when we drop out of delegated compositing. This is essentially
  // a binary of "full damage needed" or "no full damage needed" for the primary
  // plane.
  gfx::Rect overlay_damage_rect_;

  // The union of the current frame's overlays that were promoted from surface
  // content passes to be read on the subsequent frame. This is used to
  // correctly damage surface content backings if we had previously removed
  // damage due to overlay occlusion.
  gfx::Rect previous_frame_overlay_rect_;
};

}  // namespace viz

#endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_PROCESSOR_WIN_H_