// 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_DISPLAY_SCHEDULER_BASE_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_SCHEDULER_BASE_H_

#include <optional>

#include "base/containers/flat_set.h"
#include "base/memory/raw_ptr.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "components/viz/common/display/display_scheduler_draw_result.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/service/display/display_damage_tracker.h"
#include "components/viz/service/performance_hint/hint_session.h"
#include "components/viz/service/viz_service_export.h"
#include "ui/gfx/presentation_feedback.h"

namespace viz {

class DisplayDamageTracker;

// |frame_time| is the the start of the VSync interval of this frame.
// |expected_display_time| is used as video timestamps for capturing frame
// sinks. DisplayScheduler passes the end of current VSync interval.
struct VIZ_SERVICE_EXPORT DrawAndSwapParams {
  DrawAndSwapParams();
  DrawAndSwapParams(const DrawAndSwapParams& other);
  DrawAndSwapParams(DrawAndSwapParams&& other);
  DrawAndSwapParams& operator=(const DrawAndSwapParams& other);
  DrawAndSwapParams& operator=(DrawAndSwapParams&& other);
  ~DrawAndSwapParams();

  BeginFrameArgs begin_frame_args;
  base::TimeTicks expected_display_time;
  int max_pending_swaps = -1;
  std::optional<int64_t> choreographer_vsync_id;
  std::optional<PossibleDeadline> selected_deadline;
};

class VIZ_SERVICE_EXPORT DisplaySchedulerClient {
 public:
  virtual ~DisplaySchedulerClient() = default;

  virtual bool DrawAndSwap(const DrawAndSwapParams& params) = 0;
  virtual void DidFinishFrame(const BeginFrameId& frame_id,
                              DisplaySchedulerDrawResult result) = 0;
  virtual int GetCurrentAllocatedBuffers() const;
};

class VIZ_SERVICE_EXPORT DisplaySchedulerBase
    : public DisplayDamageTracker::Delegate {
 public:
  DisplaySchedulerBase();
  ~DisplaySchedulerBase() override;

  void SetClient(DisplaySchedulerClient* client);

  virtual void SetDamageTracker(DisplayDamageTracker* damage_tracker);
  virtual void SetVisible(bool visible) = 0;
  virtual void ForceImmediateSwapIfPossible() = 0;
  virtual void SetNeedsOneBeginFrame(const BeginFrameArgs& args,
                                     bool needs_draw) = 0;
  virtual void DidSwapBuffers() = 0;
  virtual void DidReceiveSwapBuffersAck() = 0;
  virtual void OutputSurfaceLost() = 0;
  // ReportFrameTime can use ADPF hints. If ADPF hints are used they will be run
  // with the |boost_type| boost type.
  virtual void ReportFrameTime(
      base::TimeDelta frame_time,
      base::flat_set<base::PlatformThreadId> animation_thread_ids,
      base::flat_set<base::PlatformThreadId> renderer_main_thread_ids,
      base::TimeTicks draw_start,
      HintSession::BoostType boost_type) = 0;
  virtual void OnPresentationFeedback(
      const gfx::PresentationFeedback& feedback,
      int64_t choreographer_vsync_id,
      base::TimeTicks frame_time,
      base::TimeDelta interval,
      std::optional<PossibleDeadline> selected_deadline) = 0;
  virtual void NotifyMinSupportedVsyncInterval(
      base::TimeDelta min_vsync_interval) {}

 protected:
  raw_ptr<DisplaySchedulerClient> client_ = nullptr;
  raw_ptr<DisplayDamageTracker> damage_tracker_ = nullptr;
};

}  // namespace viz

#endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_SCHEDULER_BASE_H_
