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/stl_util.h" | 10 #include "base/stl_util.h" |
10 #include "base/trace_event/trace_event.h" | 11 #include "base/trace_event/trace_event.h" |
11 #include "cc/output/output_surface.h" | 12 #include "cc/output/output_surface.h" |
12 | 13 |
13 namespace cc { | 14 namespace cc { |
14 | 15 |
15 DisplayScheduler::DisplayScheduler(BeginFrameSource* begin_frame_source, | 16 DisplayScheduler::DisplayScheduler(BeginFrameSource* begin_frame_source, |
16 base::SingleThreadTaskRunner* task_runner, | 17 base::SingleThreadTaskRunner* task_runner, |
17 int max_pending_swaps) | 18 int max_pending_swaps) |
18 : begin_frame_source_(begin_frame_source), | 19 : begin_frame_source_(begin_frame_source), |
19 task_runner_(task_runner), | 20 task_runner_(task_runner), |
| 21 inside_surface_damaged_(false), |
20 output_surface_lost_(false), | 22 output_surface_lost_(false), |
21 root_surface_resources_locked_(true), | 23 root_surface_resources_locked_(true), |
22 inside_begin_frame_deadline_interval_(false), | 24 inside_begin_frame_deadline_interval_(false), |
23 needs_draw_(false), | 25 needs_draw_(false), |
24 expecting_root_surface_damage_because_of_resize_(false), | 26 expecting_root_surface_damage_because_of_resize_(false), |
25 all_active_child_surfaces_ready_to_draw_(false), | 27 all_active_child_surfaces_ready_to_draw_(false), |
26 pending_swaps_(0), | 28 pending_swaps_(0), |
27 max_pending_swaps_(max_pending_swaps), | 29 max_pending_swaps_(max_pending_swaps), |
28 observing_begin_frame_source_(false), | 30 observing_begin_frame_source_(false), |
29 root_surface_damaged_(false), | 31 root_surface_damaged_(false), |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 SurfaceDamaged(root_surface_id); | 77 SurfaceDamaged(root_surface_id); |
76 } | 78 } |
77 | 79 |
78 // Indicates that there was damage to one of the surfaces. | 80 // Indicates that there was damage to one of the surfaces. |
79 // Has some logic to wait for multiple active surfaces before | 81 // Has some logic to wait for multiple active surfaces before |
80 // triggering the deadline. | 82 // triggering the deadline. |
81 void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) { | 83 void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) { |
82 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id", | 84 TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id", |
83 surface_id.ToString()); | 85 surface_id.ToString()); |
84 | 86 |
| 87 // We may cause a new BeginFrame to be run inside this method, but to help |
| 88 // avoid being reentrant to the caller of SurfaceDamaged, track when this is |
| 89 // happening with |inside_surface_damaged_|. |
| 90 base::AutoReset<bool>(&inside_surface_damaged_, true); |
| 91 |
85 needs_draw_ = true; | 92 needs_draw_ = true; |
86 | 93 |
87 if (surface_id == root_surface_id_) { | 94 if (surface_id == root_surface_id_) { |
88 root_surface_damaged_ = true; | 95 root_surface_damaged_ = true; |
89 expecting_root_surface_damage_because_of_resize_ = false; | 96 expecting_root_surface_damage_because_of_resize_ = false; |
90 } else { | 97 } else { |
91 child_surface_ids_damaged_.insert(surface_id); | 98 child_surface_ids_damaged_.insert(surface_id); |
92 | 99 |
93 // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts. | 100 // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts. |
94 all_active_child_surfaces_ready_to_draw_ = base::STLIncludes( | 101 all_active_child_surfaces_ready_to_draw_ = base::STLIncludes( |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 | 138 |
132 expect_damage_from_root_surface_ = root_surface_damaged_; | 139 expect_damage_from_root_surface_ = root_surface_damaged_; |
133 root_surface_damaged_ = false; | 140 root_surface_damaged_ = false; |
134 } | 141 } |
135 | 142 |
136 bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { | 143 bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { |
137 base::TimeTicks now = base::TimeTicks::Now(); | 144 base::TimeTicks now = base::TimeTicks::Now(); |
138 TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(), | 145 TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(), |
139 "now", now); | 146 "now", now); |
140 | 147 |
| 148 if (inside_surface_damaged_) { |
| 149 // Repost this so that we don't run a missed BeginFrame on the same |
| 150 // callstack. Otherwise we end up running unexpected scheduler actions |
| 151 // immediately while inside some other action (such as submitting a |
| 152 // CompositorFrame for a SurfaceFactory). |
| 153 DCHECK_EQ(args.type, BeginFrameArgs::MISSED); |
| 154 DCHECK(missed_begin_frame_task_.IsCancelled()); |
| 155 missed_begin_frame_task_.Reset(base::Bind( |
| 156 base::IgnoreResult(&DisplayScheduler::OnBeginFrameDerivedImpl), |
| 157 // The CancelableCallback will not run after it is destroyed, which |
| 158 // happens when |this| is destroyed. |
| 159 base::Unretained(this), args)); |
| 160 task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback()); |
| 161 return true; |
| 162 } |
| 163 |
141 // If we get another BeginFrame before the previous deadline, | 164 // If we get another BeginFrame before the previous deadline, |
142 // synchronously trigger the previous deadline before progressing. | 165 // synchronously trigger the previous deadline before progressing. |
143 if (inside_begin_frame_deadline_interval_) { | 166 if (inside_begin_frame_deadline_interval_) { |
144 OnBeginFrameDeadline(); | 167 OnBeginFrameDeadline(); |
145 } | 168 } |
146 | 169 |
147 // Schedule the deadline. | 170 // Schedule the deadline. |
148 current_begin_frame_args_ = args; | 171 current_begin_frame_args_ = args; |
149 current_begin_frame_args_.deadline -= | 172 current_begin_frame_args_.deadline -= |
150 BeginFrameArgs::DefaultEstimatedParentDrawTime(); | 173 BeginFrameArgs::DefaultEstimatedParentDrawTime(); |
151 inside_begin_frame_deadline_interval_ = true; | 174 inside_begin_frame_deadline_interval_ = true; |
152 ScheduleBeginFrameDeadline(); | 175 ScheduleBeginFrameDeadline(); |
153 | 176 |
| 177 // If we get another BeginFrame before a posted missed frame, just drop the |
| 178 // missed frame. Also if this was the missed frame, drop the Callback inside |
| 179 // it. Do this last because this might be the missed frame and we don't want |
| 180 // to destroy |args| prematurely. |
| 181 missed_begin_frame_task_.Cancel(); |
| 182 |
154 return true; | 183 return true; |
155 } | 184 } |
156 | 185 |
157 void DisplayScheduler::OnBeginFrameSourcePausedChanged(bool paused) { | 186 void DisplayScheduler::OnBeginFrameSourcePausedChanged(bool paused) { |
158 // BeginFrameSources used with DisplayScheduler do not make use of this | 187 // BeginFrameSources used with DisplayScheduler do not make use of this |
159 // feature. | 188 // feature. |
160 if (paused) | 189 if (paused) |
161 NOTIMPLEMENTED(); | 190 NOTIMPLEMENTED(); |
162 } | 191 } |
163 | 192 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 // We are going idle, so reset expectations. | 305 // We are going idle, so reset expectations. |
277 child_surface_ids_to_expect_damage_from_.clear(); | 306 child_surface_ids_to_expect_damage_from_.clear(); |
278 child_surface_ids_damaged_prev_.clear(); | 307 child_surface_ids_damaged_prev_.clear(); |
279 child_surface_ids_damaged_.clear(); | 308 child_surface_ids_damaged_.clear(); |
280 all_active_child_surfaces_ready_to_draw_ = true; | 309 all_active_child_surfaces_ready_to_draw_ = true; |
281 expect_damage_from_root_surface_ = false; | 310 expect_damage_from_root_surface_ = false; |
282 | 311 |
283 if (observing_begin_frame_source_) { | 312 if (observing_begin_frame_source_) { |
284 observing_begin_frame_source_ = false; | 313 observing_begin_frame_source_ = false; |
285 begin_frame_source_->RemoveObserver(this); | 314 begin_frame_source_->RemoveObserver(this); |
| 315 // A missed BeginFrame may be queued, so drop that too if we're going to |
| 316 // stop listening. |
| 317 missed_begin_frame_task_.Cancel(); |
286 } | 318 } |
287 } | 319 } |
288 } | 320 } |
289 | 321 |
290 void DisplayScheduler::OnBeginFrameDeadline() { | 322 void DisplayScheduler::OnBeginFrameDeadline() { |
291 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline"); | 323 TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline"); |
292 | 324 |
293 AttemptDrawAndSwap(); | 325 AttemptDrawAndSwap(); |
294 begin_frame_source_->DidFinishFrame(this, 0); | 326 begin_frame_source_->DidFinishFrame(this, 0); |
295 } | 327 } |
296 | 328 |
297 void DisplayScheduler::DidSwapBuffers() { | 329 void DisplayScheduler::DidSwapBuffers() { |
298 pending_swaps_++; | 330 pending_swaps_++; |
299 TRACE_EVENT_ASYNC_BEGIN1("cc", "DisplayScheduler:pending_swaps", this, | 331 TRACE_EVENT_ASYNC_BEGIN1("cc", "DisplayScheduler:pending_swaps", this, |
300 "pending_frames", pending_swaps_); | 332 "pending_frames", pending_swaps_); |
301 } | 333 } |
302 | 334 |
303 void DisplayScheduler::DidSwapBuffersComplete() { | 335 void DisplayScheduler::DidSwapBuffersComplete() { |
304 pending_swaps_--; | 336 pending_swaps_--; |
305 TRACE_EVENT_ASYNC_END1("cc", "DisplayScheduler:pending_swaps", this, | 337 TRACE_EVENT_ASYNC_END1("cc", "DisplayScheduler:pending_swaps", this, |
306 "pending_frames", pending_swaps_); | 338 "pending_frames", pending_swaps_); |
307 ScheduleBeginFrameDeadline(); | 339 ScheduleBeginFrameDeadline(); |
308 } | 340 } |
309 | 341 |
310 } // namespace cc | 342 } // namespace cc |
OLD | NEW |