OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/surfaces/display_scheduler.h" | 5 #include "cc/surfaces/display_scheduler.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
11 #include "base/trace_event/trace_event.h" | 11 #include "base/trace_event/trace_event.h" |
| 12 #include "cc/output/begin_frame_args.h" |
12 #include "cc/output/output_surface.h" | 13 #include "cc/output/output_surface.h" |
13 | 14 |
14 namespace cc { | 15 namespace cc { |
15 | 16 |
16 DisplayScheduler::DisplayScheduler(BeginFrameSource* begin_frame_source, | 17 DisplayScheduler::DisplayScheduler(base::SingleThreadTaskRunner* task_runner, |
17 base::SingleThreadTaskRunner* task_runner, | |
18 int max_pending_swaps) | 18 int max_pending_swaps) |
19 : begin_frame_source_(begin_frame_source), | 19 : client_(nullptr), |
| 20 begin_frame_source_(nullptr), |
20 task_runner_(task_runner), | 21 task_runner_(task_runner), |
21 inside_surface_damaged_(false), | 22 inside_surface_damaged_(false), |
22 visible_(false), | 23 visible_(false), |
23 output_surface_lost_(false), | 24 output_surface_lost_(false), |
24 root_surface_resources_locked_(true), | 25 root_surface_resources_locked_(true), |
25 inside_begin_frame_deadline_interval_(false), | 26 inside_begin_frame_deadline_interval_(false), |
26 needs_draw_(false), | 27 needs_draw_(false), |
27 expecting_root_surface_damage_because_of_resize_(false), | 28 expecting_root_surface_damage_because_of_resize_(false), |
28 all_active_child_surfaces_ready_to_draw_(false), | |
29 pending_swaps_(0), | 29 pending_swaps_(0), |
30 max_pending_swaps_(max_pending_swaps), | 30 max_pending_swaps_(max_pending_swaps), |
31 observing_begin_frame_source_(false), | 31 observing_begin_frames_(false), |
32 root_surface_damaged_(false), | |
33 expect_damage_from_root_surface_(false), | |
34 weak_ptr_factory_(this) { | 32 weak_ptr_factory_(this) { |
35 begin_frame_deadline_closure_ = base::Bind( | 33 begin_frame_deadline_closure_ = base::Bind( |
36 &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr()); | 34 &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr()); |
37 } | 35 } |
38 | 36 |
39 DisplayScheduler::~DisplayScheduler() { | 37 DisplayScheduler::~DisplayScheduler() { |
40 StopObservingBeginFrames(); | 38 StopObservingBeginFrames(); |
41 } | 39 } |
42 | 40 |
43 void DisplayScheduler::SetClient(DisplaySchedulerClient* client) { | 41 void DisplayScheduler::SetClient(DisplaySchedulerClient* client) { |
44 client_ = client; | 42 client_ = client; |
45 } | 43 } |
46 | 44 |
| 45 void DisplayScheduler::SetBeginFrameSource( |
| 46 DisplayBeginFrameSource* begin_frame_source) { |
| 47 begin_frame_source_ = begin_frame_source; |
| 48 begin_frame_source_->SetClient(this); |
| 49 } |
| 50 |
47 void DisplayScheduler::SetVisible(bool visible) { | 51 void DisplayScheduler::SetVisible(bool visible) { |
48 if (visible_ == visible) | 52 if (visible_ == visible) |
49 return; | 53 return; |
50 | 54 |
51 visible_ = visible; | 55 visible_ = visible; |
52 // If going invisible, we'll stop observing begin frames once we try | 56 // If going invisible, we'll stop observing begin frames once we try |
53 // to draw and fail. | 57 // to draw and fail. |
54 StartObservingBeginFrames(); | 58 StartObservingBeginFrames(); |
55 ScheduleBeginFrameDeadline(); | 59 ScheduleBeginFrameDeadline(); |
56 } | 60 } |
57 | 61 |
58 // If we try to draw when the root surface resources are locked, the | 62 // If we try to draw when the root surface resources are locked, the |
59 // draw will fail. | 63 // draw will fail. |
60 void DisplayScheduler::SetRootSurfaceResourcesLocked(bool locked) { | 64 void DisplayScheduler::SetRootSurfaceResourcesLocked(bool locked) { |
61 TRACE_EVENT1("cc", "DisplayScheduler::SetRootSurfaceResourcesLocked", | 65 TRACE_EVENT1("cc", "DisplayScheduler::SetRootSurfaceResourcesLocked", |
62 "locked", locked); | 66 "locked", locked); |
63 root_surface_resources_locked_ = locked; | 67 root_surface_resources_locked_ = locked; |
64 ScheduleBeginFrameDeadline(); | 68 ScheduleBeginFrameDeadline(); |
65 } | 69 } |
66 | 70 |
67 // This is used to force an immediate swap before a resize. | 71 // This is used to force an immediate swap before a resize. |
68 void DisplayScheduler::ForceImmediateSwapIfPossible() { | 72 void DisplayScheduler::ForceImmediateSwapIfPossible() { |
69 TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible"); | 73 TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible"); |
70 bool in_begin = inside_begin_frame_deadline_interval_; | 74 bool in_begin = inside_begin_frame_deadline_interval_; |
71 AttemptDrawAndSwap(); | 75 bool did_draw = AttemptDrawAndSwap(); |
72 if (in_begin) | 76 if (in_begin) |
73 begin_frame_source_->DidFinishFrame(this, 0); | 77 begin_frame_source_->FinishClientFrame(did_draw, needs_draw_); |
74 } | 78 } |
75 | 79 |
76 void DisplayScheduler::DisplayResized() { | 80 void DisplayScheduler::DisplayResized() { |
77 expecting_root_surface_damage_because_of_resize_ = true; | 81 expecting_root_surface_damage_because_of_resize_ = true; |
78 expect_damage_from_root_surface_ = true; | |
79 needs_draw_ = true; | 82 needs_draw_ = true; |
80 ScheduleBeginFrameDeadline(); | 83 ScheduleBeginFrameDeadline(); |
81 } | 84 } |
82 | 85 |
83 // Notification that there was a resize or the root surface changed and | 86 // Notification that there was a resize or the root surface changed and |
84 // that we should just draw immediately. | 87 // that we should just draw immediately. |
85 void DisplayScheduler::SetNewRootSurface(const SurfaceId& root_surface_id) { | 88 void DisplayScheduler::SetNewRootSurface(const SurfaceId& root_surface_id) { |
86 TRACE_EVENT0("cc", "DisplayScheduler::SetNewRootSurface"); | 89 TRACE_EVENT0("cc", "DisplayScheduler::SetNewRootSurface"); |
87 root_surface_id_ = root_surface_id; | 90 root_surface_id_ = root_surface_id; |
88 SurfaceDamaged(root_surface_id); | 91 SurfaceDamaged(root_surface_id); |
89 } | 92 } |
90 | 93 |
91 // Indicates that there was damage to one of the surfaces. | 94 // Indicates that there was damage to one of the surfaces. |
92 // Has some logic to wait for multiple active surfaces before | 95 // Has some logic to wait for multiple active surfaces before |
93 // triggering the deadline. | 96 // triggering the deadline. |
94 void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) { | 97 void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) { |
95 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id", | 98 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id", |
96 surface_id.ToString()); | 99 surface_id.ToString()); |
97 | 100 |
98 // We may cause a new BeginFrame to be run inside this method, but to help | 101 // We may cause a new BeginFrame to be run inside this method, but to help |
99 // avoid being reentrant to the caller of SurfaceDamaged, track when this is | 102 // avoid being reentrant to the caller of SurfaceDamaged, track when this is |
100 // happening with |inside_surface_damaged_|. | 103 // happening with |inside_surface_damaged_|. |
101 base::AutoReset<bool> auto_reset(&inside_surface_damaged_, true); | 104 base::AutoReset<bool> auto_reset(&inside_surface_damaged_, true); |
102 | 105 |
103 needs_draw_ = true; | 106 needs_draw_ = true; |
104 | 107 |
105 if (surface_id == root_surface_id_) { | 108 if (surface_id == root_surface_id_) |
106 root_surface_damaged_ = true; | |
107 expecting_root_surface_damage_because_of_resize_ = false; | 109 expecting_root_surface_damage_because_of_resize_ = false; |
108 } else { | |
109 child_surface_ids_damaged_.insert(surface_id); | |
110 | |
111 // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts. | |
112 all_active_child_surfaces_ready_to_draw_ = base::STLIncludes( | |
113 child_surface_ids_damaged_, child_surface_ids_to_expect_damage_from_); | |
114 } | |
115 | 110 |
116 StartObservingBeginFrames(); | 111 StartObservingBeginFrames(); |
117 ScheduleBeginFrameDeadline(); | 112 ScheduleBeginFrameDeadline(); |
118 } | 113 } |
119 | 114 |
120 void DisplayScheduler::OutputSurfaceLost() { | 115 void DisplayScheduler::OutputSurfaceLost() { |
121 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost"); | 116 TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost"); |
122 output_surface_lost_ = true; | 117 output_surface_lost_ = true; |
123 ScheduleBeginFrameDeadline(); | 118 ScheduleBeginFrameDeadline(); |
124 } | 119 } |
125 | 120 |
126 void DisplayScheduler::DrawAndSwap() { | 121 bool DisplayScheduler::DrawAndSwap() { |
127 TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap"); | 122 TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap"); |
128 DCHECK_LT(pending_swaps_, max_pending_swaps_); | 123 DCHECK_LT(pending_swaps_, max_pending_swaps_); |
129 DCHECK(!output_surface_lost_); | 124 DCHECK(!output_surface_lost_); |
130 | 125 |
131 bool success = client_->DrawAndSwap(); | 126 bool success = client_->DrawAndSwap(); |
132 if (!success) | 127 if (!success) |
133 return; | 128 return false; |
134 | |
135 child_surface_ids_to_expect_damage_from_ = | |
136 base::STLSetIntersection<std::vector<SurfaceId>>( | |
137 child_surface_ids_damaged_, child_surface_ids_damaged_prev_); | |
138 | |
139 child_surface_ids_damaged_prev_.swap(child_surface_ids_damaged_); | |
140 child_surface_ids_damaged_.clear(); | |
141 | 129 |
142 needs_draw_ = false; | 130 needs_draw_ = false; |
143 all_active_child_surfaces_ready_to_draw_ = | 131 return true; |
144 child_surface_ids_to_expect_damage_from_.empty(); | |
145 | |
146 expect_damage_from_root_surface_ = root_surface_damaged_; | |
147 root_surface_damaged_ = false; | |
148 } | 132 } |
149 | 133 |
150 bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { | 134 void DisplayScheduler::OnBeginFrame(const BeginFrameArgs& args) { |
151 base::TimeTicks now = base::TimeTicks::Now(); | 135 base::TimeTicks now = base::TimeTicks::Now(); |
152 TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(), | 136 TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(), |
153 "now", now); | 137 "now", now); |
154 | 138 |
| 139 // We always use the args, even if we post a missing_begin_frame_task. |
| 140 last_used_begin_frame_args_ = args; |
| 141 |
155 if (inside_surface_damaged_) { | 142 if (inside_surface_damaged_) { |
156 // Repost this so that we don't run a missed BeginFrame on the same | 143 // Repost this so that we don't run a missed BeginFrame on the same |
157 // callstack. Otherwise we end up running unexpected scheduler actions | 144 // callstack. Otherwise we end up running unexpected scheduler actions |
158 // immediately while inside some other action (such as submitting a | 145 // immediately while inside some other action (such as submitting a |
159 // CompositorFrame for a SurfaceFactory). | 146 // CompositorFrame for a SurfaceFactory). |
160 DCHECK_EQ(args.type, BeginFrameArgs::MISSED); | 147 DCHECK_EQ(args.type, BeginFrameArgs::MISSED); |
161 DCHECK(missed_begin_frame_task_.IsCancelled()); | 148 DCHECK(missed_begin_frame_task_.IsCancelled()); |
162 missed_begin_frame_task_.Reset(base::Bind( | 149 missed_begin_frame_task_.Reset(base::Bind( |
163 base::IgnoreResult(&DisplayScheduler::OnBeginFrameDerivedImpl), | 150 base::IgnoreResult(&DisplayScheduler::OnBeginFrame), |
164 // The CancelableCallback will not run after it is destroyed, which | 151 // The CancelableCallback will not run after it is destroyed, which |
165 // happens when |this| is destroyed. | 152 // happens when |this| is destroyed. |
166 base::Unretained(this), args)); | 153 base::Unretained(this), args)); |
167 task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback()); | 154 task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback()); |
168 return true; | 155 return; |
169 } | 156 } |
170 | 157 |
171 // Save the |BeginFrameArgs| as the callback (missed_begin_frame_task_) can be | 158 // Save the |BeginFrameArgs| as the callback (missed_begin_frame_task_) can be |
172 // destroyed if we StopObservingBeginFrames(), and it would take the |args| | 159 // destroyed if we StopObservingBeginFrames(), and it would take the |args| |
173 // with it. Instead save the args and cancel the |missed_begin_frame_task_|. | 160 // with it. Instead save the args and cancel the |missed_begin_frame_task_|. |
174 BeginFrameArgs save_args = args; | 161 BeginFrameArgs save_args = args; |
175 // If we get another BeginFrame before a posted missed frame, just drop the | 162 // If we get another BeginFrame before a posted missed frame, just drop the |
176 // missed frame. Also if this was the missed frame, drop the Callback inside | 163 // missed frame. Also if this was the missed frame, drop the Callback inside |
177 // it. | 164 // it. |
178 missed_begin_frame_task_.Cancel(); | 165 missed_begin_frame_task_.Cancel(); |
179 | 166 |
180 // If we get another BeginFrame before the previous deadline, | 167 // If we get another BeginFrame before the previous deadline, |
181 // synchronously trigger the previous deadline before progressing. | 168 // synchronously trigger the previous deadline before progressing. |
182 if (inside_begin_frame_deadline_interval_) { | 169 if (inside_begin_frame_deadline_interval_) { |
183 OnBeginFrameDeadline(); | 170 OnBeginFrameDeadline(); |
184 } | 171 } |
185 | 172 |
186 // Schedule the deadline. | 173 // Schedule the deadline. |
187 current_begin_frame_args_ = save_args; | 174 current_begin_frame_args_ = save_args; |
188 current_begin_frame_args_.deadline -= | 175 current_begin_frame_args_.deadline -= |
189 BeginFrameArgs::DefaultEstimatedParentDrawTime(); | 176 BeginFrameArgs::DefaultEstimatedParentDrawTime(); |
190 inside_begin_frame_deadline_interval_ = true; | 177 inside_begin_frame_deadline_interval_ = true; |
191 ScheduleBeginFrameDeadline(); | 178 ScheduleBeginFrameDeadline(); |
| 179 } |
192 | 180 |
193 return true; | 181 const BeginFrameArgs& DisplayScheduler::LastUsedBeginFrameArgs() const { |
| 182 return last_used_begin_frame_args_; |
194 } | 183 } |
195 | 184 |
196 void DisplayScheduler::StartObservingBeginFrames() { | 185 void DisplayScheduler::StartObservingBeginFrames() { |
197 if (!observing_begin_frame_source_ && ShouldDraw()) { | 186 if (!observing_begin_frames_ && |
198 begin_frame_source_->AddObserver(this); | 187 (ShouldDraw() || begin_frame_source_->HasObservers())) { |
199 observing_begin_frame_source_ = true; | 188 begin_frame_source_->SetClientNeedsBeginFrames(true); |
| 189 observing_begin_frames_ = true; |
200 } | 190 } |
201 } | 191 } |
202 | 192 |
203 void DisplayScheduler::StopObservingBeginFrames() { | 193 void DisplayScheduler::StopObservingBeginFrames() { |
204 if (observing_begin_frame_source_) { | 194 if (observing_begin_frames_) { |
205 begin_frame_source_->RemoveObserver(this); | 195 begin_frame_source_->SetClientNeedsBeginFrames(false); |
206 observing_begin_frame_source_ = false; | 196 observing_begin_frames_ = false; |
207 | 197 |
208 // A missed BeginFrame may be queued, so drop that too if we're going to | 198 // A missed BeginFrame may be queued, so drop that too if we're going to |
209 // stop listening. | 199 // stop listening. |
210 missed_begin_frame_task_.Cancel(); | 200 missed_begin_frame_task_.Cancel(); |
211 } | 201 } |
212 } | 202 } |
213 | 203 |
214 bool DisplayScheduler::ShouldDraw() { | 204 bool DisplayScheduler::ShouldDraw() { |
215 // Note: When any of these cases becomes true, StartObservingBeginFrames must | 205 // Note: When any of these cases becomes true, StartObservingBeginFrames must |
216 // be called to ensure the draw will happen. | 206 // be called to ensure the draw will happen. |
217 return needs_draw_ && !output_surface_lost_ && visible_; | 207 return needs_draw_ && !output_surface_lost_ && visible_; |
218 } | 208 } |
219 | 209 |
220 void DisplayScheduler::OnBeginFrameSourcePausedChanged(bool paused) { | 210 void DisplayScheduler::BeginFrameObserverStatusChanged() { |
221 // BeginFrameSources used with DisplayScheduler do not make use of this | 211 // We proactively start observing if any observer requests BeginFrames to |
222 // feature. | 212 // ensure that we call FinishClientFrame() for all of the source's frames. |
223 if (paused) | 213 StartObservingBeginFrames(); |
224 NOTIMPLEMENTED(); | 214 // Schedules an immediate deadline if all observers have responded. |
| 215 ScheduleBeginFrameDeadline(); |
225 } | 216 } |
226 | 217 |
227 base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() { | 218 base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() { |
228 if (output_surface_lost_) { | 219 if (output_surface_lost_) { |
229 TRACE_EVENT_INSTANT0("cc", "Lost output surface", TRACE_EVENT_SCOPE_THREAD); | 220 TRACE_EVENT_INSTANT0("cc", "Lost output surface", TRACE_EVENT_SCOPE_THREAD); |
230 return base::TimeTicks(); | 221 return base::TimeTicks(); |
231 } | 222 } |
232 | 223 |
233 if (pending_swaps_ >= max_pending_swaps_) { | 224 if (pending_swaps_ >= max_pending_swaps_) { |
234 TRACE_EVENT_INSTANT0("cc", "Swap throttled", TRACE_EVENT_SCOPE_THREAD); | 225 TRACE_EVENT_INSTANT0("cc", "Swap throttled", TRACE_EVENT_SCOPE_THREAD); |
235 return current_begin_frame_args_.frame_time + | 226 return current_begin_frame_args_.frame_time + |
236 current_begin_frame_args_.interval; | 227 current_begin_frame_args_.interval; |
237 } | 228 } |
238 | 229 |
239 if (!needs_draw_) { | 230 bool observers_finished_frame = |
| 231 begin_frame_source_->AllObserversFinishedFrame(); |
| 232 |
| 233 if (!needs_draw_ && !observers_finished_frame) { |
240 TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD); | 234 TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD); |
241 return current_begin_frame_args_.frame_time + | 235 return current_begin_frame_args_.frame_time + |
242 current_begin_frame_args_.interval; | 236 current_begin_frame_args_.interval; |
243 } | 237 } |
244 | 238 |
245 if (root_surface_resources_locked_) { | 239 if (root_surface_resources_locked_) { |
246 TRACE_EVENT_INSTANT0("cc", "Root surface resources locked", | 240 TRACE_EVENT_INSTANT0("cc", "Root surface resources locked", |
247 TRACE_EVENT_SCOPE_THREAD); | 241 TRACE_EVENT_SCOPE_THREAD); |
248 return current_begin_frame_args_.frame_time + | 242 return current_begin_frame_args_.frame_time + |
249 current_begin_frame_args_.interval; | 243 current_begin_frame_args_.interval; |
250 } | 244 } |
251 | 245 |
252 bool root_ready_to_draw = | 246 if (observers_finished_frame && |
253 !expect_damage_from_root_surface_ || root_surface_damaged_; | 247 !expecting_root_surface_damage_because_of_resize_) { |
254 | |
255 if (all_active_child_surfaces_ready_to_draw_ && root_ready_to_draw) { | |
256 TRACE_EVENT_INSTANT0("cc", "All active surfaces ready", | 248 TRACE_EVENT_INSTANT0("cc", "All active surfaces ready", |
257 TRACE_EVENT_SCOPE_THREAD); | 249 TRACE_EVENT_SCOPE_THREAD); |
258 return base::TimeTicks(); | 250 return base::TimeTicks(); |
259 } | 251 } |
260 | 252 |
261 // TODO(mithro): Be smarter about resize deadlines. | 253 // TODO(mithro): Be smarter about resize deadlines. |
262 if (expecting_root_surface_damage_because_of_resize_) { | 254 if (expecting_root_surface_damage_because_of_resize_) { |
263 TRACE_EVENT_INSTANT0("cc", "Entire display damaged", | 255 TRACE_EVENT_INSTANT0("cc", "Entire display damaged", |
264 TRACE_EVENT_SCOPE_THREAD); | 256 TRACE_EVENT_SCOPE_THREAD); |
265 return current_begin_frame_args_.frame_time + | 257 return current_begin_frame_args_.frame_time + |
266 current_begin_frame_args_.interval; | 258 current_begin_frame_args_.interval; |
267 } | 259 } |
268 | 260 |
269 // Use an earlier deadline if we are only waiting for the root surface | |
270 // in case our expect_damage_from_root_surface heuristic is incorrect. | |
271 // TODO(mithro): Replace this with SetNeedsBeginFrame and SwapAbort | |
272 // logic. | |
273 if (all_active_child_surfaces_ready_to_draw_ && | |
274 expect_damage_from_root_surface_) { | |
275 TRACE_EVENT_INSTANT0("cc", "Waiting for damage from root surface", | |
276 TRACE_EVENT_SCOPE_THREAD); | |
277 // This adjusts the deadline by DefaultEstimatedParentDrawTime for | |
278 // a second time. The first one represented the Surfaces draw to display | |
279 // latency. This one represents root surface commit+raster+draw latency. | |
280 // We treat the root surface differently since it lives on the same thread | |
281 // as Surfaces and waiting for it too long may push out the Surfaces draw. | |
282 // If we also assume the root surface is fast to start a commit after the | |
283 // beginning of a frame, it'll have a chance to lock its resources, which | |
284 // will cause us to wait for it to unlock its resources above. | |
285 // TODO(mithro): Replace hard coded estimates. | |
286 return current_begin_frame_args_.deadline - | |
287 BeginFrameArgs::DefaultEstimatedParentDrawTime(); | |
288 } | |
289 | |
290 TRACE_EVENT_INSTANT0("cc", "More damage expected soon", | 261 TRACE_EVENT_INSTANT0("cc", "More damage expected soon", |
291 TRACE_EVENT_SCOPE_THREAD); | 262 TRACE_EVENT_SCOPE_THREAD); |
292 return current_begin_frame_args_.deadline; | 263 return current_begin_frame_args_.deadline; |
293 } | 264 } |
294 | 265 |
295 void DisplayScheduler::ScheduleBeginFrameDeadline() { | 266 void DisplayScheduler::ScheduleBeginFrameDeadline() { |
296 TRACE_EVENT0("cc", "DisplayScheduler::ScheduleBeginFrameDeadline"); | 267 TRACE_EVENT0("cc", "DisplayScheduler::ScheduleBeginFrameDeadline"); |
297 | 268 |
298 // We need to wait for the next BeginFrame before scheduling a deadline. | 269 // We need to wait for the next BeginFrame before scheduling a deadline. |
299 if (!inside_begin_frame_deadline_interval_) { | 270 if (!inside_begin_frame_deadline_interval_) { |
(...skipping 20 matching lines...) Expand all Loading... |
320 begin_frame_deadline_task_.Reset(begin_frame_deadline_closure_); | 291 begin_frame_deadline_task_.Reset(begin_frame_deadline_closure_); |
321 | 292 |
322 base::TimeDelta delta = | 293 base::TimeDelta delta = |
323 std::max(base::TimeDelta(), desired_deadline - base::TimeTicks::Now()); | 294 std::max(base::TimeDelta(), desired_deadline - base::TimeTicks::Now()); |
324 task_runner_->PostDelayedTask(FROM_HERE, | 295 task_runner_->PostDelayedTask(FROM_HERE, |
325 begin_frame_deadline_task_.callback(), delta); | 296 begin_frame_deadline_task_.callback(), delta); |
326 TRACE_EVENT2("cc", "Using new deadline", "delta", delta.ToInternalValue(), | 297 TRACE_EVENT2("cc", "Using new deadline", "delta", delta.ToInternalValue(), |
327 "desired_deadline", desired_deadline); | 298 "desired_deadline", desired_deadline); |
328 } | 299 } |
329 | 300 |
330 void DisplayScheduler::AttemptDrawAndSwap() { | 301 bool DisplayScheduler::AttemptDrawAndSwap() { |
331 inside_begin_frame_deadline_interval_ = false; | 302 inside_begin_frame_deadline_interval_ = false; |
332 begin_frame_deadline_task_.Cancel(); | 303 begin_frame_deadline_task_.Cancel(); |
333 begin_frame_deadline_task_time_ = base::TimeTicks(); | 304 begin_frame_deadline_task_time_ = base::TimeTicks(); |
334 | 305 |
335 if (ShouldDraw()) { | 306 if (ShouldDraw()) { |
336 if (pending_swaps_ < max_pending_swaps_ && !root_surface_resources_locked_) | 307 if (pending_swaps_ < max_pending_swaps_ && !root_surface_resources_locked_) |
337 DrawAndSwap(); | 308 return DrawAndSwap(); |
338 } else { | 309 } else if (!begin_frame_source_->HasObservers()) { |
339 // We are going idle, so reset expectations. | 310 // We are going idle, so reset expectations. |
340 child_surface_ids_to_expect_damage_from_.clear(); | 311 // TODO(eseckler): Should we avoid going idle if |
341 child_surface_ids_damaged_prev_.clear(); | 312 // expecting_root_surface_damage_because_of_resize_ is true? |
342 child_surface_ids_damaged_.clear(); | 313 expecting_root_surface_damage_because_of_resize_ = false; |
343 all_active_child_surfaces_ready_to_draw_ = true; | |
344 expect_damage_from_root_surface_ = false; | |
345 | 314 |
346 StopObservingBeginFrames(); | 315 StopObservingBeginFrames(); |
347 } | 316 } |
| 317 |
| 318 return false; |
348 } | 319 } |
349 | 320 |
350 void DisplayScheduler::OnBeginFrameDeadline() { | 321 void DisplayScheduler::OnBeginFrameDeadline() { |
351 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline"); | 322 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline"); |
352 | 323 |
353 AttemptDrawAndSwap(); | 324 bool did_draw = AttemptDrawAndSwap(); |
354 begin_frame_source_->DidFinishFrame(this, 0); | 325 begin_frame_source_->FinishClientFrame(did_draw, needs_draw_); |
355 } | 326 } |
356 | 327 |
357 void DisplayScheduler::DidSwapBuffers() { | 328 void DisplayScheduler::DidSwapBuffers() { |
358 pending_swaps_++; | 329 pending_swaps_++; |
359 TRACE_EVENT_ASYNC_BEGIN1("cc", "DisplayScheduler:pending_swaps", this, | 330 TRACE_EVENT_ASYNC_BEGIN1("cc", "DisplayScheduler:pending_swaps", this, |
360 "pending_frames", pending_swaps_); | 331 "pending_frames", pending_swaps_); |
361 } | 332 } |
362 | 333 |
363 void DisplayScheduler::DidReceiveSwapBuffersAck() { | 334 void DisplayScheduler::DidReceiveSwapBuffersAck() { |
364 pending_swaps_--; | 335 pending_swaps_--; |
365 TRACE_EVENT_ASYNC_END1("cc", "DisplayScheduler:pending_swaps", this, | 336 TRACE_EVENT_ASYNC_END1("cc", "DisplayScheduler:pending_swaps", this, |
366 "pending_frames", pending_swaps_); | 337 "pending_frames", pending_swaps_); |
367 ScheduleBeginFrameDeadline(); | 338 ScheduleBeginFrameDeadline(); |
368 } | 339 } |
369 | 340 |
370 } // namespace cc | 341 } // namespace cc |
OLD | NEW |