OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef SERVICES_GFX_COMPOSITOR_BACKEND_VSYNC_SCHEDULER_H_ | |
6 #define SERVICES_GFX_COMPOSITOR_BACKEND_VSYNC_SCHEDULER_H_ | |
7 | |
8 #include <limits> | |
9 #include <memory> | |
10 #include <mutex> | |
11 | |
12 #include "base/callback.h" | |
13 #include "base/macros.h" | |
14 #include "base/memory/ref_counted.h" | |
15 #include "base/task_runner.h" | |
16 #include "services/gfx/compositor/backend/scheduler.h" | |
17 | |
18 namespace compositor { | |
19 | |
20 // Schedules work to coincide with vsync intervals. | |
21 // | |
22 // This object is thread-safe and it intended to be used to allow one thread | |
23 // to be scheduling work for itself while another thread concurrently updates | |
24 // timing parameters. | |
25 class VsyncScheduler : public Scheduler { | |
26 public: | |
27 // Limits on allowable parameters. (Exposed for testing.) | |
28 static constexpr int64_t kMinVsyncInterval = 1000; // 1000 Hz | |
viettrungluu
2016/01/04 21:08:24
You need to declare storage for these (in the .cc)
jeffbrown
2016/01/16 03:28:31
Hah! You're right. I'd interpreted constexpr as
| |
29 static constexpr int64_t kMaxVsyncInterval = 1000000; // 1 Hz | |
30 | |
31 // Time reference. Should be MojoTimeTicksNow() except during testing. | |
32 using Clock = base::Callback<MojoTimeTicks()>; | |
33 | |
34 VsyncScheduler(const scoped_refptr<base::TaskRunner>& task_runner, | |
35 const SchedulerCallbacks& callbacks); | |
36 VsyncScheduler(const scoped_refptr<base::TaskRunner>& task_runner, | |
37 const SchedulerCallbacks& callbacks, | |
38 const Clock& clock); | |
39 ~VsyncScheduler() override; | |
40 | |
41 // Starts scheduling work and sets the scheduling parameters. | |
42 // | |
43 // |vsync_timebase| is a value in the |MojoTimeTicks| timebase which | |
44 // specifies when a recent vsync occurred and is used to determine the phase. | |
45 // | |
46 // |vsync_interval| is the number of microseconds between vsyncs which | |
47 // also determines the |FrameInfo.frame_interval| value to deliver to | |
48 // applications. | |
49 // | |
50 // |update_phase| specifies an offset relative to vsync for determining | |
51 // when updates are scheduled and the |FrameInfo.frame_time| to deliver | |
52 // to applications. | |
53 // | |
54 // |snapshot_phase| specifies an offset relative to vsync for | |
55 // determining when snapshots are scheduled and the |FrameInfo.frame_deadline| | |
56 // to deliver to applications. Must be greater than or equal to | |
57 // |update_phase|. | |
58 // | |
59 // |presentation_phase| specifies an offset relative to vsync for | |
60 // determining when frames are shown on the display output and the | |
61 // |FrameInfo.presentation_time| to deliver to applications. Must be | |
62 // greater than or equal to |snapshot_phase|. | |
63 // | |
64 // The notion of 'vsync' is somewhat abstract here. It's just a reference | |
65 // pulse but we usually interpret it as a deadline for preparing the next | |
66 // frame and submitting it to the display hardware. | |
67 // | |
68 // The phases can be positive or negative but negative offsets from vsync | |
69 // may be easier to interpret when computing deadlines. To avoid | |
70 // overflows, the values chosen for the phases should be close to 0. | |
71 // | |
72 // This function schedules an update and snapshot if not already scheduled. | |
73 // | |
74 // Returns true if the schedule was started successfully, false if the | |
75 // parameters are invalid. | |
76 bool Start(int64_t vsync_timebase, | |
77 int64_t vsync_interval, | |
78 int64_t update_phase, | |
79 int64_t snapshot_phase, | |
80 int64_t presentation_phase) { | |
81 return state_->Start(vsync_timebase, vsync_interval, update_phase, | |
82 snapshot_phase, presentation_phase); | |
83 } | |
84 | |
85 // Stops scheduling work. | |
86 // | |
87 // Previously scheduled callbacks may still be delivered. | |
88 void Stop() { state_->Stop(); } | |
89 | |
90 // |Scheduler|: | |
91 void ScheduleFrame(SchedulingMode scheduling_mode) override; | |
92 | |
93 private: | |
94 // Internal state. Held by a shared_ptr so that callbacks running on | |
95 // other threads can reference it using a weak_ptr. | |
96 class State : public std::enable_shared_from_this<State> { | |
97 public: | |
98 State(const scoped_refptr<base::TaskRunner>& task_runner, | |
99 const SchedulerCallbacks& callbacks, | |
100 const Clock& clock); | |
101 ~State(); | |
102 | |
103 MojoTimeTicks GetTimeTicksNow() { return clock_.Run(); } | |
104 | |
105 bool Start(int64_t vsync_timebase, | |
106 int64_t vsync_interval, | |
107 int64_t update_phase, | |
108 int64_t snapshot_phase, | |
109 int64_t presentation_phase); | |
110 void Stop(); | |
111 void ScheduleFrame(SchedulingMode scheduling_mode); | |
112 | |
113 private: | |
114 enum class Action { | |
115 kUpdate, | |
116 kEarlySnapshot, | |
117 kLateSnapshot, | |
118 }; | |
119 | |
120 static void DispatchThunk(const std::weak_ptr<State>& state_weak, | |
121 int32_t generation, | |
122 Action action, | |
123 int64_t update_time); | |
124 | |
125 void ScheduleLocked(MojoTimeTicks now); | |
126 void PostDispatchLocked(int64_t now, | |
127 int64_t delivery_time, | |
128 Action action, | |
129 int64_t update_time); | |
130 | |
131 void Dispatch(int32_t generation, Action action, int64_t update_time); | |
132 void SetFrameInfoLocked(mojo::gfx::composition::FrameInfo* frame_info, | |
133 int64_t update_time); | |
134 | |
135 const scoped_refptr<base::TaskRunner> task_runner_; | |
136 const SchedulerCallbacks callbacks_; | |
137 const Clock clock_; | |
138 | |
139 // Parameters and state guarded by |mutex_|. | |
140 std::mutex mutex_; | |
141 bool running_ = false; | |
142 int32_t generation_ = 0; | |
143 int64_t vsync_timebase_ = 0; | |
144 int64_t vsync_interval_ = 0; | |
145 int64_t update_phase_ = 0; | |
146 int64_t snapshot_phase_ = 0; | |
147 int64_t presentation_phase_ = 0; | |
148 bool need_update_ = false; | |
149 bool pending_dispatch_ = false; | |
150 int64_t last_delivered_update_time_ = std::numeric_limits<int64_t>::min(); | |
151 | |
152 DISALLOW_COPY_AND_ASSIGN(State); | |
153 }; | |
154 | |
155 const std::shared_ptr<State> state_; | |
156 | |
157 DISALLOW_COPY_AND_ASSIGN(VsyncScheduler); | |
158 }; | |
159 | |
160 } // namespace compositor | |
161 | |
162 #endif // SERVICES_GFX_COMPOSITOR_BACKEND_VSYNC_SCHEDULER_H_ | |
OLD | NEW |