| Index: cc/scheduler/scheduler_state_machine.cc | 
| diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc | 
| index 4a9a2e0991914bfea1843ceea75f23397ea56d63..b917e27f95989e7f00ee2cb7cedd39084140d00b 100644 | 
| --- a/cc/scheduler/scheduler_state_machine.cc | 
| +++ b/cc/scheduler/scheduler_state_machine.cc | 
| @@ -25,11 +25,15 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) | 
| begin_main_frame_state_(BEGIN_MAIN_FRAME_STATE_IDLE), | 
| forced_redraw_state_(FORCED_REDRAW_STATE_IDLE), | 
| commit_count_(0), | 
| -      current_frame_number_(0), | 
| -      last_frame_number_submit_performed_(-1), | 
| -      last_frame_number_draw_performed_(-1), | 
| -      last_frame_number_begin_main_frame_sent_(-1), | 
| -      last_frame_number_invalidate_compositor_frame_sink_performed_(-1), | 
| +      begin_frame_source_id_(0), | 
| +      current_frame_number_(1), | 
| +      last_frame_number_submit_performed_(0), | 
| +      last_frame_number_draw_performed_(0), | 
| +      last_frame_number_begin_main_frame_sent_(0), | 
| +      last_frame_number_invalidate_compositor_frame_sink_performed_(0), | 
| +      last_frame_number_pending_tree_was_fresh_(0), | 
| +      last_frame_number_active_tree_was_fresh_(0), | 
| +      last_frame_number_compositor_frame_was_fresh_(0), | 
| draw_funnel_(false), | 
| send_begin_main_frame_funnel_(true), | 
| invalidate_compositor_frame_sink_funnel_(false), | 
| @@ -207,6 +211,7 @@ void SchedulerStateMachine::AsValueInto( | 
|  | 
| state->BeginDictionary("minor_state"); | 
| state->SetInteger("commit_count", commit_count_); | 
| +  state->SetInteger("begin_frame_source_id", begin_frame_source_id_); | 
| state->SetInteger("current_frame_number", current_frame_number_); | 
| state->SetInteger("last_frame_number_submit_performed", | 
| last_frame_number_submit_performed_); | 
| @@ -214,6 +219,12 @@ void SchedulerStateMachine::AsValueInto( | 
| last_frame_number_draw_performed_); | 
| state->SetInteger("last_frame_number_begin_main_frame_sent", | 
| last_frame_number_begin_main_frame_sent_); | 
| +  state->SetInteger("last_frame_number_pending_tree_was_fresh", | 
| +                    last_frame_number_pending_tree_was_fresh_); | 
| +  state->SetInteger("last_frame_number_active_tree_was_fresh", | 
| +                    last_frame_number_active_tree_was_fresh_); | 
| +  state->SetInteger("last_frame_number_compositor_frame_was_fresh", | 
| +                    last_frame_number_compositor_frame_was_fresh_); | 
| state->SetBoolean("funnel: draw_funnel", draw_funnel_); | 
| state->SetBoolean("funnel: send_begin_main_frame_funnel", | 
| send_begin_main_frame_funnel_); | 
| @@ -589,10 +600,22 @@ void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) { | 
| last_commit_had_no_updates_ = commit_has_no_updates; | 
| begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE; | 
|  | 
| -  if (!commit_has_no_updates) { | 
| -    // Pending tree only exists if commit had updates. | 
| +  if (commit_has_no_updates) { | 
| +    // Pending tree might still exist from prior commit. | 
| +    if (has_pending_tree_) { | 
| +      DCHECK(settings_.main_frame_before_activation_enabled); | 
| +      last_frame_number_pending_tree_was_fresh_ = | 
| +          last_frame_number_begin_main_frame_sent_; | 
| +    } else { | 
| +      last_frame_number_active_tree_was_fresh_ = | 
| +          last_frame_number_begin_main_frame_sent_; | 
| +    } | 
| +  } else { | 
| +    // We have a new pending tree. | 
| has_pending_tree_ = true; | 
| pending_tree_is_ready_for_activation_ = false; | 
| +    last_frame_number_pending_tree_was_fresh_ = | 
| +        last_frame_number_begin_main_frame_sent_; | 
| wait_for_ready_to_draw_ = settings_.commit_to_active_tree; | 
| } | 
|  | 
| @@ -824,9 +847,24 @@ bool SchedulerStateMachine::ProactiveBeginFrameWanted() const { | 
| return false; | 
| } | 
|  | 
| -void SchedulerStateMachine::OnBeginImplFrame() { | 
| +void SchedulerStateMachine::OnBeginImplFrame(uint64_t source_id, | 
| +                                             uint64_t sequence_number) { | 
| +  if (source_id != begin_frame_source_id_) { | 
| +    begin_frame_source_id_ = source_id; | 
| +    current_frame_number_ = sequence_number; | 
| + | 
| +    // Consider us up to date up to the previous BeginFrame. | 
| +    last_frame_number_active_tree_was_fresh_ = current_frame_number_ - 1; | 
| +    last_frame_number_pending_tree_was_fresh_ = | 
| +        last_frame_number_active_tree_was_fresh_; | 
| +    last_frame_number_compositor_frame_was_fresh_ = | 
| +        last_frame_number_active_tree_was_fresh_; | 
| +  } | 
| + | 
| +  DCHECK_GE(sequence_number, current_frame_number_); | 
| + | 
| begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; | 
| -  current_frame_number_++; | 
| +  current_frame_number_ = sequence_number; | 
|  | 
| last_commit_had_no_updates_ = false; | 
| did_draw_in_last_frame_ = false; | 
| @@ -840,6 +878,18 @@ void SchedulerStateMachine::OnBeginImplFrame() { | 
| // "Drain" the PrepareTiles funnel. | 
| if (prepare_tiles_funnel_ > 0) | 
| prepare_tiles_funnel_--; | 
| + | 
| +  // Update frame numbers for freshness if no updates are requested. | 
| +  if (!needs_begin_main_frame_) { | 
| +    if (has_pending_tree_) { | 
| +      last_frame_number_pending_tree_was_fresh_ = current_frame_number_; | 
| +    } else { | 
| +      last_frame_number_active_tree_was_fresh_ = current_frame_number_; | 
| + | 
| +      if (!needs_redraw_) | 
| +        last_frame_number_compositor_frame_was_fresh_ = current_frame_number_; | 
| +    } | 
| +  } | 
| } | 
|  | 
| void SchedulerStateMachine::OnBeginImplFrameDeadline() { | 
| @@ -985,6 +1035,8 @@ void SchedulerStateMachine::DidSubmitCompositorFrame() { | 
|  | 
| did_submit_in_last_frame_ = true; | 
| last_frame_number_submit_performed_ = current_frame_number_; | 
| +  last_frame_number_compositor_frame_was_fresh_ = | 
| +      last_frame_number_active_tree_was_fresh_; | 
| } | 
|  | 
| void SchedulerStateMachine::DidReceiveCompositorFrameAck() { | 
|  |