// 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_INTERFACE_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_PROCESSOR_INTERFACE_H_

#include <memory>
#include <optional>
#include <vector>

#include "base/containers/flat_map.h"
#include "build/build_config.h"
#include "components/viz/common/quads/aggregated_render_pass.h"
#include "components/viz/common/resources/shared_image_format.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/viz_service_export.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/service/gpu_task_scheduler_helper.h"
#include "gpu/ipc/common/surface_handle.h"
#include "ui/gfx/ca_layer_result.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rrect_f.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/overlay_priority_hint.h"
#include "ui/gfx/swap_result.h"

#if BUILDFLAG(IS_WIN)
#include "components/viz/service/display/dc_layer_overlay.h"
#endif

#if BUILDFLAG(IS_APPLE)
#include "components/viz/service/display/ca_layer_overlay.h"
#endif

namespace gpu {
class SharedImageManager;
}

namespace viz {
struct DebugRendererSettings;
class DisplayResourceProvider;
class OutputSurface;
class RendererSettings;

// This class is called inside the DirectRenderer to separate the contents that
// should be sent into the overlay system and the contents that requires
// compositing from the DirectRenderer. This class has different subclass
// implemented by different platforms. This class defines the minimal interface
// for overlay processing that each platform needs to implement.
class VIZ_SERVICE_EXPORT OverlayProcessorInterface {
 public:
  using PlatformOverlayCandidate = OverlayCandidate;
  using CandidateList = OverlayCandidateList;
  using FilterOperationsMap =
      base::flat_map<AggregatedRenderPassId,
                     raw_ptr<cc::FilterOperations, CtnExperimental>>;

  virtual bool DisableSplittingQuads() const;

  // Used by DCLayerOverlayProcessor and OverlayProcessorUsingStrategy.
  static void RecordOverlayDamageRectHistograms(
      bool is_overlay,
      bool has_occluding_surface_damage,
      bool zero_damage_rect);

  static std::unique_ptr<OverlayProcessorInterface> CreateOverlayProcessor(
      OutputSurface* output_surface,
      gpu::SurfaceHandle surface_handle,
      const OutputSurface::Capabilities& capabilities,
      DisplayCompositorMemoryAndTaskController* display_controller,
      gpu::SharedImageManager* shared_image_manager,
      const RendererSettings& renderer_settings,
      const DebugRendererSettings* debug_settings);

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

  virtual ~OverlayProcessorInterface() = default;

  virtual bool IsOverlaySupported() const = 0;

  virtual gfx::Rect GetAndResetOverlayDamage() = 0;

  // 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.
  virtual bool NeedsSurfaceDamageRectList() const = 0;

  struct PrimaryPlaneParams {
    const gfx::Size viewport_size;
    const gfx::Size resource_size_in_pixels;
    bool supports_hdr = false;
    bool is_opaque = false;

    // Used by Ozone to create a dummy buffer to test overlay support.
    const SharedImageFormat si_format;
    // Used by Ozone to create a dummy buffer to test overlay support. Used by
    // Android to determine the output color space, especially for HDR output.
    const gfx::ColorSpace color_space;

#if BUILDFLAG(IS_OZONE)
    // Ozone requires checking for overlay support with an actual buffer. To
    // create the primary plane, `OverlayProcessorOzone` will use an existing
    // `overlay_testing_mailbox` (usually, the last swapped primary plane
    // buffer) or will make a dummy buffer using `si_format` and `color_space`.
    const gpu::Mailbox overlay_testing_mailbox;
#endif
  };

  // Attempts to replace quads from the specified root render pass with overlays
  // or CALayers. This must be called every frame.
  virtual void ProcessForOverlays(
      DisplayResourceProvider* resource_provider,
      AggregatedRenderPassList* render_passes,
      const SkM44& output_color_matrix,
      SurfaceDamageRectList surface_damage_rect_list,
      const PrimaryPlaneParams& primary_plane_params,
      CandidateList* overlay_candidates,
      gfx::Rect* damage_rect) = 0;

  // Before the overlay refactor to use OverlayProcessorOnGpu, overlay
  // candidates are stored inside DirectRenderer. Those overlay candidates are
  // later sent over to the GPU thread by SkiaRenderer. This helper function
  // will be called by DirectRenderer to take these overlay candidates inside
  // overlay processor to avoid sending over DirectRenderer implementation. This
  // is overridden by each platform that is ready to send overlay candidates
  // inside |OverlayProcessor|. Must be called before ScheduleOverlays().
  virtual void TakeOverlayCandidates(CandidateList* candidate_list) {}

  // TODO(weiliangc): Make it pure virtual after it is implemented by every
  // subclass.
  virtual void ScheduleOverlays(
      DisplayResourceProvider* display_resource_provider);
  // This is a signal from Display::DidReceiveSwapBuffersAck. This is used as
  // approximate signale for when the overlays are presented.
  virtual void OverlayPresentationComplete();

  // These two functions are used by Android SurfaceControl.
  virtual void SetDisplayTransformHint(gfx::OverlayTransform transform) {}
  virtual void SetViewportSize(const gfx::Size& size) {}

  // Overlay processor uses a frame counter to determine the potential power
  // benefits of individual overlay candidates.
  virtual void SetFrameSequenceNumber(uint64_t frame_sequence_number) {}

  // If true, page fullscreen mode is enabled for this frame.
  virtual void SetIsPageFullscreen(bool enabled) {}

  virtual gfx::CALayerResult GetCALayerErrorCode() const;

  // Supports gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL_CLOCKWISE_90 and
  // gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL_CLOCKWISE_270 transforms.
  virtual bool SupportsFlipRotateTransform() const;

  // This is used by the overlay processor on platforms that support delegated
  // ink. It marks the current frame as having delegated ink, and is cleared in
  // the next ProcessForOverlays call.
  virtual void SetFrameHasDelegatedInk() {}

  // Notifies the OverlayProcessor about the status of the last swap.
  virtual void OnSwapBuffersComplete(gfx::SwapResult swap_result) {}

 protected:
  OverlayProcessorInterface() = default;

  static OverlayCandidate CreatePrimaryPlane(const PrimaryPlaneParams& params);
};

}  // namespace viz

#endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_PROCESSOR_INTERFACE_H_
