File: display_scheduler.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (174 lines) | stat: -rw-r--r-- 6,587 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Copyright 2015 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_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_SCHEDULER_H_

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

#include "base/cancelable_callback.h"
#include "base/memory/raw_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/service/display/display_scheduler_base.h"
#include "components/viz/service/display/pending_swap_params.h"
#include "components/viz/service/viz_service_export.h"

namespace viz {

class HintSession;
class HintSessionFactory;

class VIZ_SERVICE_EXPORT DisplayScheduler
    : public DisplaySchedulerBase,
      public DynamicBeginFrameDeadlineOffsetSource {
 public:
  // `max_pending_swaps_120hz`, if positive, is used as the number of pending
  // swaps while running at 120hz. Otherwise, this will fallback to
  // `max_pending_swaps`.
  DisplayScheduler(BeginFrameSource* begin_frame_source,
                   base::SingleThreadTaskRunner* task_runner,
                   PendingSwapParams pending_swap_params,
                   HintSessionFactory* hint_session_factory = nullptr,
                   bool wait_for_all_surfaces_before_draw = false);

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

  ~DisplayScheduler() override;

  // DisplaySchedulerBase implementation.
  void SetDamageTracker(DisplayDamageTracker* damage_tracker) override;
  void SetVisible(bool visible) override;
  void ForceImmediateSwapIfPossible() override;
  void SetNeedsOneBeginFrame(bool needs_draw) override;
  void DidSwapBuffers() override;
  void DidReceiveSwapBuffersAck() override;
  void OutputSurfaceLost() override;
  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) override;

  // DisplayDamageTracker::Delegate implementation.
  void OnDisplayDamaged(SurfaceId surface_id) override;
  void OnRootFrameMissing(bool missing) override;
  void OnPendingSurfacesChanged() override;

  // DynamicBeginFrameDeadlineOffsetSource:
  base::TimeDelta GetDeadlineOffset(base::TimeDelta interval) const override;

 protected:
  class BeginFrameObserver;
  class BeginFrameRequestObserverImpl;

  bool OnBeginFrame(const BeginFrameArgs& args);
  void OnBeginFrameContinuation(const BeginFrameArgs& args);
  int MaxPendingSwaps() const;

  base::TimeTicks current_frame_display_time() const {
    return current_begin_frame_args_.frame_time +
           current_begin_frame_args_.interval;
  }

  // These values inidicate how a response to the BeginFrame should be
  // scheduled.
  enum class BeginFrameDeadlineMode {
    // Respond immediately. This means either all clients have responded with a
    // BeginFrameAck so there is nothing to wait for, or DrawAndSwap cannot
    // happen anymore (for example, OutputSurface is lost) and we might as well
    // respond right now.
    kImmediate,
    // Schedule a task at the the end of BeginFrame interval minus the estimated
    // time to run DrawAndSwap. This indicates that all requirements for calling
    // DrawAndSwap are met, but we just want to give clients as much time as
    // possible to send CompositorFrames.
    kRegular,
    // Schedule a response at the end of the BeginFrame interval. This usually
    // indicates that some requirements for calling DrawAndSwap are not
    // currently met (for example, the previous swap is not acked yet) and
    // we would like to wait as long as possible to see if DrawAndSwap becomes
    // possible.
    kLate,
    // A response to the BeginFrame cannot be scheduled right now. This means we
    // have an unlimited deadline and some clients haven't responded to the
    // BeginFrame yet so we need to wait longer.
    kNone
  };

  static base::TimeTicks DesiredBeginFrameDeadlineTime(
      BeginFrameDeadlineMode deadline_mode,
      BeginFrameArgs begin_frame_args);

  BeginFrameDeadlineMode AdjustedBeginFrameDeadlineMode() const;
  BeginFrameDeadlineMode DesiredBeginFrameDeadlineMode() const;
  virtual void ScheduleBeginFrameDeadline();
  bool AttemptDrawAndSwap();
  void OnBeginFrameDeadline();
  bool DrawAndSwap();
  void MaybeStartObservingBeginFrames();
  void StartObservingBeginFrames();
  void StopObservingBeginFrames();
  bool ShouldDraw() const;
  void DidFinishFrame(bool did_draw);
  // Updates |has_pending_surfaces_| and returns whether its value changed.
  bool UpdateHasPendingSurfaces();
  void MaybeCreateHintSessions(
      base::flat_set<base::PlatformThreadId> animation_thread_ids,
      base::flat_set<base::PlatformThreadId> renderer_main_thread_ids);

  std::unique_ptr<BeginFrameObserver> begin_frame_observer_;
  raw_ptr<BeginFrameSource> begin_frame_source_;
  raw_ptr<base::SingleThreadTaskRunner> task_runner_;

  BeginFrameArgs current_begin_frame_args_;
  base::RepeatingClosure begin_frame_deadline_closure_;
  base::DeadlineTimer begin_frame_deadline_timer_;
  base::TimeTicks begin_frame_deadline_task_time_;

  base::CancelableOnceClosure missed_begin_frame_task_;
  bool inside_surface_damaged_;

  bool visible_;
  bool output_surface_lost_;

  bool inside_begin_frame_deadline_interval_;
  bool needs_draw_;
  bool has_pending_surfaces_;

  int next_swap_id_;
  int pending_swaps_;
  const PendingSwapParams pending_swap_params_;
  bool wait_for_all_surfaces_before_draw_;

  bool observing_begin_frame_source_;

  const raw_ptr<HintSessionFactory> hint_session_factory_;

  struct AdpfSessionState {
    base::flat_set<base::PlatformThreadId> thread_ids;
    std::unique_ptr<HintSession> hint_session;
    bool create_session_for_current_thread_ids_failed = false;
    HintSession::SessionType type;

    explicit AdpfSessionState(HintSession::SessionType type);
    AdpfSessionState(AdpfSessionState&&);
    ~AdpfSessionState();
  };
  std::vector<AdpfSessionState> session_states_;

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

}  // namespace viz

#endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_SCHEDULER_H_