chromium/ash/rounded_display/rounded_display_provider.h

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_ROUNDED_DISPLAY_ROUNDED_DISPLAY_PROVIDER_H_
#define ASH_ROUNDED_DISPLAY_ROUNDED_DISPLAY_PROVIDER_H_

#include <memory>
#include <vector>

#include "ash/ash_export.h"
#include "base/memory/weak_ptr.h"
#include "ui/display/display.h"
#include "ui/gfx/geometry/rounded_corners_f.h"

namespace aura {
class Window;
}  // namespace aura

namespace ash {

class RoundedDisplayGutter;
class RoundedDisplayGutterFactory;
class RoundedDisplayProviderTestApi;
class RoundedDisplayHost;

// Provides an API to create software-based rounded corners for a given display.
// It manages the rounded corners for the display and renders them by submitting
// independent compositor frame to the display compositor.
class ASH_EXPORT RoundedDisplayProvider {
 public:
  // Strategy decides the direction in which RoundedDisplayGutters are created.
  enum class Strategy {
    // Overlay gutters are created is the scanout direction of the display
    // panel.
    kScanout,
    // Overlay gutters are created is the direction that is perpendicular to the
    // scanout direction of display_panel.
    kOther
  };

  static std::unique_ptr<RoundedDisplayProvider> Create(int64_t display_id);

  RoundedDisplayProvider(
      const int64_t display_id,
      std::unique_ptr<RoundedDisplayGutterFactory> gutter_factory);

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

  ~RoundedDisplayProvider();

  // Creates RoundedDisplayGutter based on the specified `strategy` for the
  // display and initializes the `RoundedDisplayHost`. Note: Need to call
  // `UpdateRoundedDisplaySurface()` to show the rounded-display masks.
  void Init(const gfx::RoundedCornersF& panel_radii, Strategy strategy);

  // Update the window hierarchy to which the `host_window_` is attached to.
  // Needed to be called when the window_tree_host for the display is updated
  // and swapped with the window_tree_host of another display.
  void UpdateHostParent();

  bool UpdateRoundedDisplaySurface();

  int64_t display_id() const { return display_id_; }

 private:
  friend class RoundedDisplayProviderTestApi;

  // Returns gutters in draw order. Gutters in the front are drawn on top.
  // Note: `DeleteGutters()` and `CreateGutters()` invalidates the pointers.
  void GetGuttersInDrawOrder(std::vector<RoundedDisplayGutter*>& gutters) const;

  bool ShouldSubmitNewCompositorFrame(const display::Display& display) const;

  // Creates RoundedDisplayGutters if needed and returns true if we created
  // gutters else returns false.
  // To minimize the use of overlay planes, we only create a gutter if it has
  // at least a single non-zero corner mask drawn into it.
  // For example, for a display that doesn't have rounded bottom edges, and
  // based on the `strategy_`, we need to create upper and lower OverlayGutters,
  // we will skip the creation of the lower OverlayGutter.
  bool CreateGutters(const display::Display& display,
                     const gfx::RoundedCornersF& panel_radii);

  // Initialize the `RoundedDisplayHost`, attach the `host_window_` to the
  // window hierarchy of the display.
  void InitializeHost();

  // The id of the display for which the provider creates rounded corners
  // for.
  const int64_t display_id_;

  // The current display state for which rounded display is enabled.
  float current_device_scale_factor_ = 0.0;
  display::Display::Rotation current_logical_rotation_ =
      display::Display::Rotation::ROTATE_0;
  gfx::RoundedCornersF current_panel_radii_;

  // The specified strategy to determine direction of overlay gutters.
  Strategy strategy_ = Strategy::kScanout;

  // Stores the overlay gutters that are created based on the `strategy_`.
  std::vector<std::unique_ptr<RoundedDisplayGutter>> overlay_gutters_;

  // OverlayRoundedDisplayGutter creation is delegated to this factory.
  std::unique_ptr<RoundedDisplayGutterFactory> gutter_factory_;

  // Represents the surface on which the `host_` render the mask textures of the
  // rounded-display corners.
  std::unique_ptr<aura::Window> host_window_;

  // Responsible to render the mask textures by submitting compositor frames.
  std::unique_ptr<RoundedDisplayHost> host_;

  base::WeakPtrFactory<RoundedDisplayProvider> weak_ptr_factory_{this};
};

}  // namespace ash

#endif  // ASH_ROUNDED_DISPLAY_ROUNDED_DISPLAY_PROVIDER_H_