chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.h

// 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 UI_OZONE_PLATFORM_DRM_GPU_DRM_OVERLAY_MANAGER_H_
#define UI_OZONE_PLATFORM_DRM_GPU_DRM_OVERLAY_MANAGER_H_

#include <memory>
#include <vector>

#include "base/containers/circular_deque.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/lru_cache.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/public/hardware_capabilities.h"
#include "ui/ozone/public/overlay_candidates_ozone.h"
#include "ui/ozone/public/overlay_manager_ozone.h"

namespace ui {

class OverlaySurfaceCandidate;

// Ozone DRM extension of the OverlayManagerOzone interface. It queries the
// DrmDevice to see if an overlay configuration will work and keeps an MRU cache
// of recent configurations.
class DrmOverlayManager : public OverlayManagerOzone {
 public:
  DrmOverlayManager(bool handle_overlays_swap_failure,
                    bool allow_sync_and_real_buffer_page_flip_testing);

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

  ~DrmOverlayManager() override;

  // OverlayManagerOzone:
  std::unique_ptr<OverlayCandidatesOzone> CreateOverlayCandidates(
      gfx::AcceleratedWidget w) override;

  // Called when notified by the DRM thread of a display configuration change.
  // Resets the cache of OverlaySurfaceCandidates and if they can be displayed
  // as an overlay. Requests an updated HardwareCapabilities for any observing
  // OverlayProcessors.
  void DisplaysConfigured();

  // Checks if overlay candidates can be displayed as overlays. Modifies
  // |candidates| to indicate if they can.
  void CheckOverlaySupport(std::vector<OverlaySurfaceCandidate>* candidates,
                           gfx::AcceleratedWidget widget);

  void StartObservingHardwareCapabilities(
      gfx::AcceleratedWidget widget,
      HardwareCapabilitiesCallback receive_callback);
  void StopObservingHardwareCapabilities(gfx::AcceleratedWidget widget);

  virtual void GetHardwareCapabilities(
      gfx::AcceleratedWidget widget,
      HardwareCapabilitiesCallback& receive_callback) = 0;

  // Should be called by the overlay processor to indicate if a widget has a
  // candidate that requires an overlay. This is to prioritize which display
  // gets the overlay in a multiple display environment.
  void RegisterOverlayRequirement(gfx::AcceleratedWidget widget,
                                  bool requires_overlay);

  // Should be called by the overlay processor to indicate status of the last
  // swap.
  void OnSwapBuffersComplete(gfx::SwapResult swap_result);

  // Should be called by the overlay processor once it gets hardware
  // capabilities.
  void SetSupportedBufferFormats(
      gfx::AcceleratedWidget widget,
      base::flat_set<gfx::BufferFormat> supported_buffer_formats);

  // Should be called by the overlay processor to indicate what overlay types
  // are promoted. This is later used in |OnSwapBuffersComplete| to distinguish
  // overlay types. Can be empty.
  void OnPromotedOverlayTypes(
      std::vector<gfx::OverlayType> promoted_overlay_types);

 protected:
  // Sends a request to see if overlay configuration will work. Implementations
  // should call UpdateCacheForOverlayCandidates() with the response.
  virtual void SendOverlayValidationRequest(
      const std::vector<OverlaySurfaceCandidate>& candidates,
      gfx::AcceleratedWidget widget) = 0;

  // Similar to SendOverlayValidationRequest() but instead of calling
  // UpdateCacheForOverlayCandidates(), returns the result synchronously.
  virtual std::vector<OverlayStatus> SendOverlayValidationRequestSync(
      const std::vector<OverlaySurfaceCandidate>& candidates,
      gfx::AcceleratedWidget widget) = 0;

  // Perform basic validation to see if |candidate| is a valid request.
  bool CanHandleCandidate(const OverlaySurfaceCandidate& candidate,
                          gfx::AcceleratedWidget widget) const;

  // Checks if gfx::BufferFormat that overlay candidate requires is supported
  // by hardware.
  bool IsBufferFormatSupported(gfx::BufferFormat required_overlay_buffer_format,
                               gfx::AcceleratedWidget widget) const;

  // Updates the MRU cache for overlay configuration |candidates| with |status|.
  void UpdateCacheForOverlayCandidates(
      const std::vector<OverlaySurfaceCandidate>& candidates,
      const gfx::AcceleratedWidget widget,
      const std::vector<OverlayStatus>& status);

  base::TimeTicks disallow_fullscreen_overlays_end_time() const {
    return disallow_fullscreen_overlays_end_time_;
  }

 private:
  // Value for the request cache, that keeps track of how many times a
  // specific validation has been requested, if there is a GPU validation
  // in flight, and at last the result of the validation.
  struct OverlayValidationCacheValue {
    OverlayValidationCacheValue();
    OverlayValidationCacheValue(OverlayValidationCacheValue&& other);
    ~OverlayValidationCacheValue();
    OverlayValidationCacheValue& operator=(OverlayValidationCacheValue&& other);

    int request_num = 0;
    std::vector<OverlayStatus> status;
  };

  using OverlayCandidatesListCache =
      base::LRUCache<std::vector<OverlaySurfaceCandidate>,
                     OverlayValidationCacheValue>;

  // Map of each widget to the cache of list of all OverlaySurfaceCandidate
  // instances which have been requested for validation and/or validated.
  std::map<gfx::AcceleratedWidget, OverlayCandidatesListCache>
      widget_cache_map_;

  base::flat_set<gfx::AcceleratedWidget> widgets_with_required_overlays_;

  std::map<gfx::AcceleratedWidget, HardwareCapabilitiesCallback>
      hardware_capabilities_callbacks_;

  base::flat_map<gfx::AcceleratedWidget, base::flat_set<gfx::BufferFormat>>
      per_widget_overlay_supported_buffer_formats_;

  // A simple queue of bools that helps to identify buffer swaps.
  base::circular_deque<std::vector<gfx::OverlayType>> in_flight_overlay_types_;

  // Tell the manager to handle overlay swap failures.
  // TODO(b/331237773): Unfortunately, the kHandleOverlaysSwapFailure feature
  // cannot be checked by the this overlay manager in ozone directly as it
  // creates a circular dependency. That's why this control bool is here. Remove
  // this once kHandleOverlaysSwapFailure is removed and DrmOverlayManager is
  // always handling swap failures.
  const bool handle_overlays_swap_failure_;

  // Control variable, which allows to promote fullscreen overlay candidates
  // without drm testing if |handle_overlays_swap_failure_| is true.
  bool allow_skip_fullscreen_overlay_drm_test_ = true;
  // The end time when fullscreen overlay drm test is allowed again. This is
  // set when fullscreen overlay fails and the manager has to start to do
  // drm test of fullscreen overlays again.
  base::TimeTicks disallow_fullscreen_overlays_end_time_;

  THREAD_CHECKER(thread_checker_);
};

}  // namespace ui

#endif  // UI_OZONE_PLATFORM_DRM_GPU_DRM_OVERLAY_MANAGER_H_