Chromium Code Reviews| Index: cc/surfaces/display_scheduler.cc |
| diff --git a/cc/surfaces/display_scheduler.cc b/cc/surfaces/display_scheduler.cc |
| index d26d1b6306973debcf5abde447dfa0c928b981f7..7c662340948954c78eb9cb9696df358819b6cd28 100644 |
| --- a/cc/surfaces/display_scheduler.cc |
| +++ b/cc/surfaces/display_scheduler.cc |
| @@ -97,7 +97,12 @@ void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) { |
| if (!output_surface_lost_ && !observing_begin_frame_source_) { |
| observing_begin_frame_source_ = true; |
| + // When we call AddObserver() this will cause a missed BeginFrame to |
| + // occur. We need to detect this and not process it immediately in the |
| + // same call stack. |
| + inside_add_observer_ = true; |
|
sunnyps
2016/07/27 02:00:14
nit: base::AutoReset<bool> mark_inside(&inside_add
danakj
2016/07/27 02:19:04
Done.
|
| begin_frame_source_->AddObserver(this); |
| + inside_add_observer_ = false; |
| } |
| ScheduleBeginFrameDeadline(); |
| @@ -138,6 +143,24 @@ bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { |
| TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(), |
| "now", now); |
| + if (inside_add_observer_) { |
| + // Repost this so that we don't run a missed BeginFrame on the same |
| + // callstack. Otherwise we end up running unexpected scheduler actions |
| + // immediately while inside some other action (such as submitting a frame |
| + // for a SurfaceFactory). |
| + DCHECK_EQ(args.type, BeginFrameArgs::MISSED); |
| + DCHECK(missed_begin_frame_task_.IsCancelled()); |
| + missed_begin_frame_task_.Reset(base::Bind( |
| + base::IgnoreResult(&DisplayScheduler::OnBeginFrameDerivedImpl), |
| + weak_ptr_factory_.GetWeakPtr(), args)); |
| + task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback()); |
| + return true; |
| + } else { |
| + // If we get another BeginFrame before a posted missed frame, just drop the |
| + // missed frame. |
| + missed_begin_frame_task_.Cancel(); |
| + } |
| + |
| // If we get another BeginFrame before the previous deadline, |
| // synchronously trigger the previous deadline before progressing. |
| if (inside_begin_frame_deadline_interval_) { |