chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.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 UI_OZONE_PLATFORM_DRM_GPU_DRM_GPU_DISPLAY_MANAGER_H_
#define UI_OZONE_PLATFORM_DRM_GPU_DRM_GPU_DISPLAY_MANAGER_H_

#include <stdint.h>

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

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "ui/display/types/display_constants.h"
#include "ui/ozone/platform/drm/common/display_types.h"
#include "ui/ozone/platform/drm/gpu/drm_gpu_util.h"

using drmModeModeInfo = struct _drmModeModeInfo;

namespace display {
struct ColorCalibration;
struct ColorTemperatureAdjustment;
struct DisplayConfigurationParams;
struct GammaAdjustment;
}  // namespace display

namespace ui {

class DrmDeviceManager;
class DrmDisplay;
class ScreenManager;

class DrmGpuDisplayManager {
 public:
  DrmGpuDisplayManager(ScreenManager* screen_manager,
                       DrmDeviceManager* drm_device_manager);

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

  ~DrmGpuDisplayManager();

  // Sets a callback that will be notified when display configuration may have
  // changed, so we should update state for managing overlays.
  void SetDisplaysConfiguredCallback(base::RepeatingClosure callback);

  // Returns a list of the connected displays. When this is called the list of
  // displays is refreshed.
  MovableDisplaySnapshots GetDisplays();

  // Takes/releases the control of the DRM devices.
  bool TakeDisplayControl();
  void RelinquishDisplayControl();

  // Whether or not a udev display change event triggered by a DRM property
  // should go through or get blocked.
  bool ShouldDisplayEventTriggerConfiguration(
      const EventPropertyMap& event_props);

  bool ConfigureDisplays(
      const std::vector<display::DisplayConfigurationParams>& config_requests,
      display::ModesetFlags modeset_flags,
      std::vector<display::DisplayConfigurationParams>& out_requests);
  bool SetHdcpKeyProp(int64_t display_id, const std::string& key);
  bool GetHDCPState(int64_t display_id,
                    display::HDCPState* state,
                    display::ContentProtectionMethod* protection_method);
  bool SetHDCPState(int64_t display_id,
                    display::HDCPState state,
                    display::ContentProtectionMethod protection_method);
  void SetColorTemperatureAdjustment(
      int64_t display_id,
      const display::ColorTemperatureAdjustment& cta);
  void SetColorCalibration(int64_t display_id,
                           const display::ColorCalibration& calibration);
  void SetGammaAdjustment(int64_t display_id,
                          const display::GammaAdjustment& adjustment);
  void SetBackgroundColor(int64_t display_id, const uint64_t background_color);
  bool SetPrivacyScreen(int64_t display_id, bool enabled);
  std::optional<std::vector<float>> GetSeamlessRefreshRates(
      int64_t display_id) const;

 private:
  friend class DrmGpuDisplayManagerTest;

  DrmDisplay* FindDisplay(int64_t display_id) const;
  DrmDisplay* FindDisplayByConnectorId(uint32_t connector_id) const;

  // Notify ScreenManager of all the displays that were present before the
  // update but are gone after the update.
  void NotifyScreenManager(
      const std::vector<std::unique_ptr<DrmDisplay>>& new_displays,
      const std::vector<std::unique_ptr<DrmDisplay>>& old_displays) const;

  // Test modesets with |controllers_to_configure|, but with all
  // possible permutations of CRTC-connector pairings. Returns true if one of
  // the permutation leads to a successful test modest.
  bool RetryTestConfigureDisplaysWithAlternateCrtcs(
      const std::vector<display::DisplayConfigurationParams>& config_requests,
      const std::vector<ControllerConfigParams>& controllers_to_configure);

  // Replace the CRTC of all displays and display controllers specified in
  // |controllers_to_configure| by its connector with their new CRTC.
  bool UpdateDisplaysWithNewCrtcs(
      const std::vector<ControllerConfigParams>& controllers_to_configure);

  // Get the display state associated with |config_requests| if there was a
  // successful test configuration before the commit modeset call.
  std::vector<ControllerConfigParams> GetLatestModesetTestConfig(
      const std::vector<display::DisplayConfigurationParams>& config_requests);

  // Finds a mode that matches the size and timing specified by |request_mode|
  // and returns an owned copy. Prioritizes choosing modes natively belonging to
  // |display|, and attempts panel-fitting from |all_displays| if needed. If
  // |is_seamless| is true, performs additional verification that the returned
  // mode can be configured seamlessly. Returns nullptr if no matching mode was
  // found.
  std::unique_ptr<drmModeModeInfo> FindModeForDisplay(
      const display::DisplayMode& request_mode,
      const DrmDisplay& display,
      bool is_seamless);

  const raw_ptr<ScreenManager> screen_manager_;         // Not owned.
  const raw_ptr<DrmDeviceManager> drm_device_manager_;  // Not owned.

  std::vector<std::unique_ptr<DrmDisplay>> displays_;

  base::RepeatingClosure displays_configured_callback_;

  // A map of successful test display config request and the config params. The
  // map is cleared on every commit modeset, or whenever the displays and
  // controllers are recreated in GetDisplays().
  base::flat_map<std::string, std::vector<ControllerConfigParams>>
      successful_test_config_params_;
};

}  // namespace ui

#endif  // UI_OZONE_PLATFORM_DRM_GPU_DRM_GPU_DISPLAY_MANAGER_H_