// Copyright 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/scheduler/scheduler_state_machine.h"

#include "base/format_macros.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
#include "base/values.h"
#include "ui/gfx/frame_time.h"

namespace cc {

SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
    : settings_(settings),
      output_surface_state_(OUTPUT_SURFACE_LOST),
      begin_impl_frame_state_(BEGIN_IMPL_FRAME_STATE_IDLE),
      commit_state_(COMMIT_STATE_IDLE),
      forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
      commit_count_(0),
      current_frame_number_(0),
      last_frame_number_animate_performed_(-1),
      last_frame_number_swap_performed_(-1),
      last_frame_number_swap_requested_(-1),
      last_frame_number_begin_main_frame_sent_(-1),
      animate_funnel_(false),
      perform_swap_funnel_(false),
      request_swap_funnel_(false),
      send_begin_main_frame_funnel_(false),
      prepare_tiles_funnel_(0),
      consecutive_checkerboard_animations_(0),
      max_pending_swaps_(1),
      pending_swaps_(0),
      needs_redraw_(false),
      needs_animate_(false),
      needs_prepare_tiles_(false),
      needs_commit_(false),
      inside_poll_for_anticipated_draw_triggers_(false),
      visible_(false),
      can_start_(false),
      can_draw_(false),
      has_pending_tree_(false),
      pending_tree_is_ready_for_activation_(false),
      active_tree_needs_first_draw_(false),
      did_create_and_initialize_first_output_surface_(false),
      impl_latency_takes_priority_(false),
      skip_next_begin_main_frame_to_reduce_latency_(false),
      skip_begin_main_frame_to_reduce_latency_(false),
      continuous_painting_(false),
      children_need_begin_frames_(false),
      defer_commits_(false),
      last_commit_had_no_updates_(false) {
}

const char* SchedulerStateMachine::OutputSurfaceStateToString(
    OutputSurfaceState state) {
  switch (state) {
    case OUTPUT_SURFACE_ACTIVE:
      return "OUTPUT_SURFACE_ACTIVE";
    case OUTPUT_SURFACE_LOST:
      return "OUTPUT_SURFACE_LOST";
    case OUTPUT_SURFACE_CREATING:
      return "OUTPUT_SURFACE_CREATING";
    case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
      return "OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT";
    case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
      return "OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION";
  }
  NOTREACHED();
  return "???";
}

const char* SchedulerStateMachine::BeginImplFrameStateToString(
    BeginImplFrameState state) {
  switch (state) {
    case BEGIN_IMPL_FRAME_STATE_IDLE:
      return "BEGIN_IMPL_FRAME_STATE_IDLE";
    case BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING:
      return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING";
    case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME:
      return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME";
    case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE:
      return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE";
  }
  NOTREACHED();
  return "???";
}

const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
  switch (state) {
    case COMMIT_STATE_IDLE:
      return "COMMIT_STATE_IDLE";
    case COMMIT_STATE_BEGIN_MAIN_FRAME_SENT:
      return "COMMIT_STATE_BEGIN_MAIN_FRAME_SENT";
    case COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED:
      return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED";
    case COMMIT_STATE_READY_TO_COMMIT:
      return "COMMIT_STATE_READY_TO_COMMIT";
    case COMMIT_STATE_WAITING_FOR_ACTIVATION:
      return "COMMIT_STATE_WAITING_FOR_ACTIVATION";
    case COMMIT_STATE_WAITING_FOR_DRAW:
      return "COMMIT_STATE_WAITING_FOR_DRAW";
  }
  NOTREACHED();
  return "???";
}

const char* SchedulerStateMachine::ForcedRedrawOnTimeoutStateToString(
    ForcedRedrawOnTimeoutState state) {
  switch (state) {
    case FORCED_REDRAW_STATE_IDLE:
      return "FORCED_REDRAW_STATE_IDLE";
    case FORCED_REDRAW_STATE_WAITING_FOR_COMMIT:
      return "FORCED_REDRAW_STATE_WAITING_FOR_COMMIT";
    case FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION:
      return "FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION";
    case FORCED_REDRAW_STATE_WAITING_FOR_DRAW:
      return "FORCED_REDRAW_STATE_WAITING_FOR_DRAW";
  }
  NOTREACHED();
  return "???";
}

const char* SchedulerStateMachine::ActionToString(Action action) {
  switch (action) {
    case ACTION_NONE:
      return "ACTION_NONE";
    case ACTION_ANIMATE:
      return "ACTION_ANIMATE";
    case ACTION_SEND_BEGIN_MAIN_FRAME:
      return "ACTION_SEND_BEGIN_MAIN_FRAME";
    case ACTION_COMMIT:
      return "ACTION_COMMIT";
    case ACTION_ACTIVATE_SYNC_TREE:
      return "ACTION_ACTIVATE_SYNC_TREE";
    case ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
      return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE";
    case ACTION_DRAW_AND_SWAP_FORCED:
      return "ACTION_DRAW_AND_SWAP_FORCED";
    case ACTION_DRAW_AND_SWAP_ABORT:
      return "ACTION_DRAW_AND_SWAP_ABORT";
    case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
      return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION";
    case ACTION_PREPARE_TILES:
      return "ACTION_PREPARE_TILES";
  }
  NOTREACHED();
  return "???";
}

scoped_refptr<base::trace_event::ConvertableToTraceFormat>
SchedulerStateMachine::AsValue() const {
  scoped_refptr<base::trace_event::TracedValue> state =
      new base::trace_event::TracedValue();
  AsValueInto(state.get());
  return state;
}

void SchedulerStateMachine::AsValueInto(
    base::trace_event::TracedValue* state) const {
  state->BeginDictionary("major_state");
  state->SetString("next_action", ActionToString(NextAction()));
  state->SetString("begin_impl_frame_state",
                   BeginImplFrameStateToString(begin_impl_frame_state_));
  state->SetString("commit_state", CommitStateToString(commit_state_));
  state->SetString("output_surface_state_",
                   OutputSurfaceStateToString(output_surface_state_));
  state->SetString("forced_redraw_state",
                   ForcedRedrawOnTimeoutStateToString(forced_redraw_state_));
  state->EndDictionary();

  state->BeginDictionary("minor_state");
  state->SetInteger("commit_count", commit_count_);
  state->SetInteger("current_frame_number", current_frame_number_);
  state->SetInteger("last_frame_number_animate_performed",
                    last_frame_number_animate_performed_);
  state->SetInteger("last_frame_number_swap_performed",
                    last_frame_number_swap_performed_);
  state->SetInteger("last_frame_number_swap_requested",
                    last_frame_number_swap_requested_);
  state->SetInteger("last_frame_number_begin_main_frame_sent",
                    last_frame_number_begin_main_frame_sent_);
  state->SetBoolean("funnel: animate_funnel", animate_funnel_);
  state->SetBoolean("funnel: perform_swap_funnel", perform_swap_funnel_);
  state->SetBoolean("funnel: request_swap_funnel", request_swap_funnel_);
  state->SetBoolean("funnel: send_begin_main_frame_funnel",
                    send_begin_main_frame_funnel_);
  state->SetInteger("funnel: prepare_tiles_funnel", prepare_tiles_funnel_);
  state->SetInteger("consecutive_checkerboard_animations",
                    consecutive_checkerboard_animations_);
  state->SetInteger("max_pending_swaps_", max_pending_swaps_);
  state->SetInteger("pending_swaps_", pending_swaps_);
  state->SetBoolean("needs_redraw", needs_redraw_);
  state->SetBoolean("needs_animate_", needs_animate_);
  state->SetBoolean("needs_prepare_tiles", needs_prepare_tiles_);
  state->SetBoolean("needs_commit", needs_commit_);
  state->SetBoolean("visible", visible_);
  state->SetBoolean("can_start", can_start_);
  state->SetBoolean("can_draw", can_draw_);
  state->SetBoolean("has_pending_tree", has_pending_tree_);
  state->SetBoolean("pending_tree_is_ready_for_activation",
                    pending_tree_is_ready_for_activation_);
  state->SetBoolean("active_tree_needs_first_draw",
                    active_tree_needs_first_draw_);
  state->SetBoolean("did_create_and_initialize_first_output_surface",
                    did_create_and_initialize_first_output_surface_);
  state->SetBoolean("impl_latency_takes_priority",
                    impl_latency_takes_priority_);
  state->SetBoolean("main_thread_is_in_high_latency_mode",
                    MainThreadIsInHighLatencyMode());
  state->SetBoolean("skip_begin_main_frame_to_reduce_latency",
                    skip_begin_main_frame_to_reduce_latency_);
  state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency",
                    skip_next_begin_main_frame_to_reduce_latency_);
  state->SetBoolean("continuous_painting", continuous_painting_);
  state->SetBoolean("children_need_begin_frames", children_need_begin_frames_);
  state->SetBoolean("defer_commits", defer_commits_);
  state->EndDictionary();
}

void SchedulerStateMachine::AdvanceCurrentFrameNumber() {
  current_frame_number_++;

  animate_funnel_ = false;
  perform_swap_funnel_ = false;
  request_swap_funnel_ = false;
  send_begin_main_frame_funnel_ = false;

  // "Drain" the PrepareTiles funnel.
  if (prepare_tiles_funnel_ > 0)
    prepare_tiles_funnel_--;

  skip_begin_main_frame_to_reduce_latency_ =
      skip_next_begin_main_frame_to_reduce_latency_;
  skip_next_begin_main_frame_to_reduce_latency_ = false;
}

bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
  // These are all the cases where we normally cannot or do not want to draw
  // but, if needs_redraw_ is true and we do not draw to make forward progress,
  // we might deadlock with the main thread.
  // This should be a superset of PendingActivationsShouldBeForced() since
  // activation of the pending tree is blocked by drawing of the active tree and
  // the main thread might be blocked on activation of the most recent commit.
  if (PendingActivationsShouldBeForced())
    return true;

  // Additional states where we should abort draws.
  if (!can_draw_)
    return true;
  return false;
}

bool SchedulerStateMachine::PendingActivationsShouldBeForced() const {
  // There is no output surface to trigger our activations.
  // If we do not force activations to make forward progress, we might deadlock
  // with the main thread.
  if (output_surface_state_ == OUTPUT_SURFACE_LOST)
    return true;

  // If we're not visible, we should force activation.
  // Since we set RequiresHighResToDraw when becoming visible, we ensure that we
  // don't checkerboard until all visible resources are done. Furthermore, if we
  // do keep the pending tree around, when becoming visible we might activate
  // prematurely causing RequiresHighResToDraw flag to be reset. In all cases,
  // we can simply activate on becoming invisible since we don't need to draw
  // the active tree when we're in this state.
  if (!visible_)
    return true;

  return false;
}

bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const {
  // Don't try to initialize too early.
  if (!can_start_)
    return false;

  // We only want to start output surface initialization after the
  // previous commit is complete.
  if (commit_state_ != COMMIT_STATE_IDLE)
    return false;

  // Make sure the BeginImplFrame from any previous OutputSurfaces
  // are complete before creating the new OutputSurface.
  if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_IDLE)
    return false;

  // We want to clear the pipline of any pending draws and activations
  // before starting output surface initialization. This allows us to avoid
  // weird corner cases where we abort draws or force activation while we
  // are initializing the output surface.
  if (active_tree_needs_first_draw_ || has_pending_tree_)
    return false;

  // We need to create the output surface if we don't have one and we haven't
  // started creating one yet.
  return output_surface_state_ == OUTPUT_SURFACE_LOST;
}

bool SchedulerStateMachine::ShouldDraw() const {
  // If we need to abort draws, we should do so ASAP since the draw could
  // be blocking other important actions (like output surface initialization),
  // from occuring. If we are waiting for the first draw, then perfom the
  // aborted draw to keep things moving. If we are not waiting for the first
  // draw however, we don't want to abort for no reason.
  if (PendingDrawsShouldBeAborted())
    return active_tree_needs_first_draw_;

  // Do not draw too many times in a single frame. It's okay that we don't check
  // this before checking for aborted draws because aborted draws do not request
  // a swap.
  if (request_swap_funnel_)
    return false;

  // Don't draw if we are waiting on the first commit after a surface.
  if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE)
    return false;

  // Do not queue too many swaps.
  if (pending_swaps_ >= max_pending_swaps_)
    return false;

  // Except for the cases above, do not draw outside of the BeginImplFrame
  // deadline.
  if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
    return false;

  // Only handle forced redraws due to timeouts on the regular deadline.
  if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
    return true;

  return needs_redraw_;
}

bool SchedulerStateMachine::ShouldActivatePendingTree() const {
  // There is nothing to activate.
  if (!has_pending_tree_)
    return false;

  // We should not activate a second tree before drawing the first one.
  // Even if we need to force activation of the pending tree, we should abort
  // drawing the active tree first.
  if (active_tree_needs_first_draw_)
    return false;

  // If we want to force activation, do so ASAP.
  if (PendingActivationsShouldBeForced())
    return true;

  // At this point, only activate if we are ready to activate.
  return pending_tree_is_ready_for_activation_;
}

bool SchedulerStateMachine::ShouldAnimate() const {
  // Do not animate too many times in a single frame.
  if (animate_funnel_)
    return false;

  // Don't animate if we are waiting on the first commit after a surface.
  if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE)
    return false;

  if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING &&
      begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
    return false;

  return needs_redraw_ || needs_animate_;
}

bool SchedulerStateMachine::CouldSendBeginMainFrame() const {
  // Do not send begin main frame too many times in a single frame.
  if (send_begin_main_frame_funnel_)
    return false;

  if (!needs_commit_)
    return false;

  // We can not perform commits if we are not visible.
  if (!visible_)
    return false;

  // Do not make a new commits when it is deferred.
  if (defer_commits_)
    return false;

  return true;
}

bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
  if (!CouldSendBeginMainFrame())
    return false;

  // Only send BeginMainFrame when there isn't another commit pending already.
  if (commit_state_ != COMMIT_STATE_IDLE)
    return false;

  // Don't send BeginMainFrame early if we are prioritizing the active tree
  // because of impl_latency_takes_priority_.
  if (impl_latency_takes_priority_ &&
      (has_pending_tree_ || active_tree_needs_first_draw_)) {
    return false;
  }

  // We should not send BeginMainFrame while we are in
  // BEGIN_IMPL_FRAME_STATE_IDLE since we might have new
  // user input arriving soon.
  // TODO(brianderson): Allow sending BeginMainFrame while idle when the main
  // thread isn't consuming user input.
  if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE &&
      BeginFrameNeeded())
    return false;

  // We need a new commit for the forced redraw. This honors the
  // single commit per interval because the result will be swapped to screen.
  if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
    return true;

  // We shouldn't normally accept commits if there isn't an OutputSurface.
  if (!HasInitializedOutputSurface())
    return false;

  // SwapAck throttle the BeginMainFrames unless we just swapped.
  // TODO(brianderson): Remove this restriction to improve throughput.
  bool just_swapped_in_deadline =
      begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
      perform_swap_funnel_;
  if (pending_swaps_ >= max_pending_swaps_ && !just_swapped_in_deadline)
    return false;

  if (skip_begin_main_frame_to_reduce_latency_)
    return false;

  return true;
}

bool SchedulerStateMachine::ShouldCommit() const {
  if (commit_state_ != COMMIT_STATE_READY_TO_COMMIT)
    return false;

  // We must not finish the commit until the pending tree is free.
  if (has_pending_tree_) {
    DCHECK(settings_.main_frame_before_activation_enabled);
    return false;
  }

  // Prioritize drawing the previous commit before finishing the next commit.
  if (active_tree_needs_first_draw_)
    return false;

  return true;
}

bool SchedulerStateMachine::ShouldPrepareTiles() const {
  // PrepareTiles only really needs to be called immediately after commit
  // and then periodically after that. Use a funnel to make sure we average
  // one PrepareTiles per BeginImplFrame in the long run.
  if (prepare_tiles_funnel_ > 0)
    return false;

  // Limiting to once per-frame is not enough, since we only want to
  // prepare tiles _after_ draws. Polling for draw triggers and
  // begin-frame are mutually exclusive, so we limit to these two cases.
  if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
      !inside_poll_for_anticipated_draw_triggers_)
    return false;
  return needs_prepare_tiles_;
}

SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
  if (ShouldActivatePendingTree())
    return ACTION_ACTIVATE_SYNC_TREE;
  if (ShouldCommit())
    return ACTION_COMMIT;
  if (ShouldAnimate())
    return ACTION_ANIMATE;
  if (ShouldDraw()) {
    if (PendingDrawsShouldBeAborted())
      return ACTION_DRAW_AND_SWAP_ABORT;
    else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
      return ACTION_DRAW_AND_SWAP_FORCED;
    else
      return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
  }
  if (ShouldPrepareTiles())
    return ACTION_PREPARE_TILES;
  if (ShouldSendBeginMainFrame())
    return ACTION_SEND_BEGIN_MAIN_FRAME;
  if (ShouldBeginOutputSurfaceCreation())
    return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
  return ACTION_NONE;
}

void SchedulerStateMachine::UpdateState(Action action) {
  switch (action) {
    case ACTION_NONE:
      return;

    case ACTION_ACTIVATE_SYNC_TREE:
      UpdateStateOnActivation();
      return;

    case ACTION_ANIMATE:
      DCHECK(!animate_funnel_);
      last_frame_number_animate_performed_ = current_frame_number_;
      animate_funnel_ = true;
      needs_animate_ = false;
      // TODO(skyostil): Instead of assuming this, require the client to tell
      // us.
      SetNeedsRedraw();
      return;

    case ACTION_SEND_BEGIN_MAIN_FRAME:
      DCHECK(!has_pending_tree_ ||
             settings_.main_frame_before_activation_enabled);
      DCHECK(visible_);
      DCHECK(!send_begin_main_frame_funnel_);
      commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT;
      needs_commit_ = false;
      send_begin_main_frame_funnel_ = true;
      last_frame_number_begin_main_frame_sent_ =
          current_frame_number_;
      return;

    case ACTION_COMMIT: {
      bool commit_has_no_updates = false;
      UpdateStateOnCommit(commit_has_no_updates);
      return;
    }

    case ACTION_DRAW_AND_SWAP_FORCED:
    case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
      bool did_request_swap = true;
      UpdateStateOnDraw(did_request_swap);
      return;
    }

    case ACTION_DRAW_AND_SWAP_ABORT: {
      bool did_request_swap = false;
      UpdateStateOnDraw(did_request_swap);
      return;
    }

    case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
      DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
      output_surface_state_ = OUTPUT_SURFACE_CREATING;

      // The following DCHECKs make sure we are in the proper quiescent state.
      // The pipeline should be flushed entirely before we start output
      // surface creation to avoid complicated corner cases.
      DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
      DCHECK(!has_pending_tree_);
      DCHECK(!active_tree_needs_first_draw_);
      return;

    case ACTION_PREPARE_TILES:
      UpdateStateOnPrepareTiles();
      return;
  }
}

void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) {
  commit_count_++;

  if (!commit_has_no_updates)
    animate_funnel_ = false;

  if (commit_has_no_updates || settings_.main_frame_before_activation_enabled) {
    commit_state_ = COMMIT_STATE_IDLE;
  } else if (settings_.impl_side_painting) {
    commit_state_ = COMMIT_STATE_WAITING_FOR_ACTIVATION;
  } else {
    commit_state_ = settings_.main_thread_should_always_be_low_latency
                        ? COMMIT_STATE_WAITING_FOR_DRAW
                        : COMMIT_STATE_IDLE;
  }

  // If we are impl-side-painting but the commit was aborted, then we behave
  // mostly as if we are not impl-side-painting since there is no pending tree.
  has_pending_tree_ = settings_.impl_side_painting && !commit_has_no_updates;

  // Update state related to forced draws.
  if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) {
    forced_redraw_state_ = has_pending_tree_
                               ? FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
                               : FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
  }

  // Update the output surface state.
  DCHECK_NE(output_surface_state_, OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
  if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
    if (has_pending_tree_) {
      output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
    } else {
      output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
      needs_redraw_ = true;
    }
  }

  // Update state if we have a new active tree to draw, or if the active tree
  // was unchanged but we need to do a forced draw.
  if (!has_pending_tree_ &&
      (!commit_has_no_updates ||
       forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)) {
    needs_redraw_ = true;
    active_tree_needs_first_draw_ = true;
  }

  // This post-commit work is common to both completed and aborted commits.
  pending_tree_is_ready_for_activation_ = false;

  if (continuous_painting_)
    needs_commit_ = true;
  last_commit_had_no_updates_ = commit_has_no_updates;
}

void SchedulerStateMachine::UpdateStateOnActivation() {
  if (commit_state_ == COMMIT_STATE_WAITING_FOR_ACTIVATION) {
    commit_state_ = settings_.main_thread_should_always_be_low_latency
                        ? COMMIT_STATE_WAITING_FOR_DRAW
                        : COMMIT_STATE_IDLE;
  }

  if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
    output_surface_state_ = OUTPUT_SURFACE_ACTIVE;

  if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION)
    forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;

  has_pending_tree_ = false;
  pending_tree_is_ready_for_activation_ = false;
  active_tree_needs_first_draw_ = true;
  needs_redraw_ = true;
}

void SchedulerStateMachine::UpdateStateOnDraw(bool did_request_swap) {
  if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
    forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;

  if (commit_state_ == COMMIT_STATE_WAITING_FOR_DRAW)
    commit_state_ = COMMIT_STATE_IDLE;

  needs_redraw_ = false;
  active_tree_needs_first_draw_ = false;

  if (did_request_swap) {
    DCHECK(!request_swap_funnel_);
    request_swap_funnel_ = true;
    last_frame_number_swap_requested_ = current_frame_number_;
  }
}

void SchedulerStateMachine::UpdateStateOnPrepareTiles() {
  needs_prepare_tiles_ = false;
}

void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() {
  TRACE_EVENT_INSTANT0("cc",
                       "Scheduler: SkipNextBeginMainFrameToReduceLatency",
                       TRACE_EVENT_SCOPE_THREAD);
  skip_next_begin_main_frame_to_reduce_latency_ = true;
}

bool SchedulerStateMachine::BeginFrameNeededForChildren() const {
  if (HasInitializedOutputSurface())
    return children_need_begin_frames_;

  return false;
}

bool SchedulerStateMachine::BeginFrameNeeded() const {
  // We can't handle BeginFrames when output surface isn't initialized.
  // TODO(brianderson): Support output surface creation inside a BeginFrame.
  if (!HasInitializedOutputSurface())
    return false;

  if (SupportsProactiveBeginFrame()) {
    return (BeginFrameNeededToAnimateOrDraw() ||
            BeginFrameNeededForChildren() ||
            ProactiveBeginFrameWanted());
  }

  // Proactive BeginFrames are bad for the synchronous compositor because we
  // have to draw when we get the BeginFrame and could end up drawing many
  // duplicate frames if our new frame isn't ready in time.
  // To poll for state with the synchronous compositor without having to draw,
  // we rely on ShouldPollForAnticipatedDrawTriggers instead.
  // Synchronous compositor doesn't have a browser.
  DCHECK(!children_need_begin_frames_);
  return BeginFrameNeededToAnimateOrDraw();
}

bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
  // ShouldPollForAnticipatedDrawTriggers is what we use in place of
  // ProactiveBeginFrameWanted when we are using the synchronous
  // compositor.
  if (!SupportsProactiveBeginFrame()) {
    return !BeginFrameNeededToAnimateOrDraw() && ProactiveBeginFrameWanted();
  }

  // Non synchronous compositors should rely on
  // ProactiveBeginFrameWanted to poll for state instead.
  return false;
}

// Note: If SupportsProactiveBeginFrame is false, the scheduler should poll
// for changes in it's draw state so it can request a BeginFrame when it's
// actually ready.
bool SchedulerStateMachine::SupportsProactiveBeginFrame() const {
  // It is undesirable to proactively request BeginFrames if we are
  // using a synchronous compositor because we *must* draw for every
  // BeginFrame, which could cause duplicate draws.
  return !settings_.using_synchronous_renderer_compositor;
}

void SchedulerStateMachine::SetChildrenNeedBeginFrames(
    bool children_need_begin_frames) {
  children_need_begin_frames_ = children_need_begin_frames;
}

void SchedulerStateMachine::SetDeferCommits(bool defer_commits) {
  defer_commits_ = defer_commits;
}

// These are the cases where we definitely (or almost definitely) have a
// new frame to animate and/or draw and can draw.
bool SchedulerStateMachine::BeginFrameNeededToAnimateOrDraw() const {
  // The forced draw respects our normal draw scheduling, so we need to
  // request a BeginImplFrame for it.
  if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
    return true;

  return needs_animate_ || needs_redraw_;
}

// These are cases where we are very likely to draw soon, but might not
// actually have a new frame to draw when we receive the next BeginImplFrame.
// Proactively requesting the BeginImplFrame helps hide the round trip latency
// of the SetNeedsBeginFrame request that has to go to the Browser.
bool SchedulerStateMachine::ProactiveBeginFrameWanted() const {
  // Do not be proactive when invisible.
  if (!visible_)
    return false;

  // We should proactively request a BeginImplFrame if a commit is pending
  // because we will want to draw if the commit completes quickly.
  if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE)
    return true;

  // If the pending tree activates quickly, we'll want a BeginImplFrame soon
  // to draw the new active tree.
  if (has_pending_tree_)
    return true;

  // Changing priorities may allow us to activate (given the new priorities),
  // which may result in a new frame.
  if (needs_prepare_tiles_)
    return true;

  // If we just sent a swap request, it's likely that we are going to produce
  // another frame soon. This helps avoid negative glitches in our
  // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame
  // provider and get sampled at an inopportune time, delaying the next
  // BeginImplFrame.
  if (request_swap_funnel_)
    return true;

  // If the last commit was aborted because of early out (no updates), we should
  // still want a begin frame in case there is a commit coming again.
  if (last_commit_had_no_updates_)
    return true;

  return false;
}

void SchedulerStateMachine::OnBeginImplFrame() {
  AdvanceCurrentFrameNumber();
  DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE)
      << AsValue()->ToString();
  begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
  last_commit_had_no_updates_ = false;
}

void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() {
  DCHECK_EQ(begin_impl_frame_state_,
            BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)
      << AsValue()->ToString();
  begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
}

void SchedulerStateMachine::OnBeginImplFrameDeadline() {
  DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
      << AsValue()->ToString();
  begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
}

void SchedulerStateMachine::OnBeginImplFrameIdle() {
  DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
      << AsValue()->ToString();
  begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
}

SchedulerStateMachine::BeginImplFrameDeadlineMode
SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const {
  if (ShouldTriggerBeginImplFrameDeadlineImmediately()) {
    return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE;
  } else if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) {
    // We have an animation or fast input path on the impl thread that wants
    // to draw, so don't wait too long for a new active tree.
    // If we are swap throttled we should wait until we are unblocked.
    return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR;
  } else {
    // The impl thread doesn't have anything it wants to draw and we are just
    // waiting for a new active tree or we are swap throttled. In short we are
    // blocked.
    return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE;
  }
}

bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately()
    const {
  // TODO(brianderson): This should take into account multiple commit sources.

  if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
    return false;

  // If we've lost the output surface, end the current BeginImplFrame ASAP
  // so we can start creating the next output surface.
  if (output_surface_state_ == OUTPUT_SURFACE_LOST)
    return true;

  // SwapAck throttle the deadline since we wont draw and swap anyway.
  if (pending_swaps_ >= max_pending_swaps_)
    return false;

  if (active_tree_needs_first_draw_)
    return true;

  if (!needs_redraw_)
    return false;

  // This is used to prioritize impl-thread draws when the main thread isn't
  // producing anything, e.g., after an aborted commit. We also check that we
  // don't have a pending tree -- otherwise we should give it a chance to
  // activate.
  // TODO(skyostil): Revisit this when we have more accurate deadline estimates.
  if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_)
    return true;

  // Prioritize impl-thread draws in impl_latency_takes_priority_ mode.
  if (impl_latency_takes_priority_)
    return true;

  return false;
}

bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
  // If a commit is pending before the previous commit has been drawn, we
  // are definitely in a high latency mode.
  if (CommitPending() && (active_tree_needs_first_draw_ || has_pending_tree_))
    return true;

  // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main
  // thread is in a low latency mode.
  if (send_begin_main_frame_funnel_ &&
      (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING ||
       begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME))
    return false;

  // If there's a commit in progress it must either be from the previous frame
  // or it started after the impl thread's deadline. In either case the main
  // thread is in high latency mode.
  if (CommitPending())
    return true;

  // Similarly, if there's a pending tree the main thread is in high latency
  // mode, because either
  //   it's from the previous frame
  // or
  //   we're currently drawing the active tree and the pending tree will thus
  //   only be drawn in the next frame.
  if (has_pending_tree_)
    return true;

  if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
    // Even if there's a new active tree to draw at the deadline or we've just
    // swapped it, it may have been triggered by a previous BeginImplFrame, in
    // which case the main thread is in a high latency mode.
    return (active_tree_needs_first_draw_ || perform_swap_funnel_) &&
           !send_begin_main_frame_funnel_;
  }

  // If the active tree needs its first draw in any other state, we know the
  // main thread is in a high latency mode.
  return active_tree_needs_first_draw_;
}

void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
  AdvanceCurrentFrameNumber();
  inside_poll_for_anticipated_draw_triggers_ = true;
}

void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() {
  inside_poll_for_anticipated_draw_triggers_ = false;
}

void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }

void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }

void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }

void SchedulerStateMachine::SetNeedsAnimate() {
  needs_animate_ = true;
}

void SchedulerStateMachine::SetNeedsPrepareTiles() {
  if (!needs_prepare_tiles_) {
    TRACE_EVENT0("cc", "SchedulerStateMachine::SetNeedsPrepareTiles");
    needs_prepare_tiles_ = true;
  }
}

void SchedulerStateMachine::SetMaxSwapsPending(int max) {
  max_pending_swaps_ = max;
}

void SchedulerStateMachine::DidSwapBuffers() {
  pending_swaps_++;
  DCHECK_LE(pending_swaps_, max_pending_swaps_);
  DCHECK(!perform_swap_funnel_);

  perform_swap_funnel_ = true;
  last_frame_number_swap_performed_ = current_frame_number_;
}

void SchedulerStateMachine::DidSwapBuffersComplete() {
  DCHECK_GT(pending_swaps_, 0);
  pending_swaps_--;
}

void SchedulerStateMachine::SetImplLatencyTakesPriority(
    bool impl_latency_takes_priority) {
  impl_latency_takes_priority_ = impl_latency_takes_priority;
}

void SchedulerStateMachine::DidDrawIfPossibleCompleted(DrawResult result) {
  switch (result) {
    case INVALID_RESULT:
      NOTREACHED() << "Uninitialized DrawResult.";
      break;
    case DRAW_ABORTED_CANT_DRAW:
    case DRAW_ABORTED_CONTEXT_LOST:
      NOTREACHED() << "Invalid return value from DrawAndSwapIfPossible:"
                   << result;
      break;
    case DRAW_SUCCESS:
      consecutive_checkerboard_animations_ = 0;
      forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
      break;
    case DRAW_ABORTED_CHECKERBOARD_ANIMATIONS:
      needs_redraw_ = true;

      // If we're already in the middle of a redraw, we don't need to
      // restart it.
      if (forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
        return;

      needs_commit_ = true;
      consecutive_checkerboard_animations_++;
      if (settings_.timeout_and_draw_when_animation_checkerboards &&
          consecutive_checkerboard_animations_ >=
              settings_.maximum_number_of_failed_draws_before_draw_is_forced_) {
        consecutive_checkerboard_animations_ = 0;
        // We need to force a draw, but it doesn't make sense to do this until
        // we've committed and have new textures.
        forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
      }
      break;
    case DRAW_ABORTED_MISSING_HIGH_RES_CONTENT:
      // It's not clear whether this missing content is because of missing
      // pictures (which requires a commit) or because of memory pressure
      // removing textures (which might not).  To be safe, request a commit
      // anyway.
      needs_commit_ = true;
      break;
  }
}

void SchedulerStateMachine::SetNeedsCommit() {
  needs_commit_ = true;
}

void SchedulerStateMachine::NotifyReadyToCommit() {
  DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED)
      << AsValue()->ToString();
  commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
  // In main thread low latency mode, commit should happen right after
  // BeginFrame, meaning when this function is called, next action should be
  // commit.
  if (settings_.main_thread_should_always_be_low_latency)
    DCHECK(ShouldCommit());
}

void SchedulerStateMachine::BeginMainFrameAborted(CommitEarlyOutReason reason) {
  DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
  switch (reason) {
    case CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST:
    case CommitEarlyOutReason::ABORTED_NOT_VISIBLE:
    case CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT:
      commit_state_ = COMMIT_STATE_IDLE;
      SetNeedsCommit();
      return;
    case CommitEarlyOutReason::FINISHED_NO_UPDATES:
      bool commit_has_no_updates = true;
      UpdateStateOnCommit(commit_has_no_updates);
      return;
  }
}

void SchedulerStateMachine::DidPrepareTiles() {
  needs_prepare_tiles_ = false;
  // "Fill" the PrepareTiles funnel.
  prepare_tiles_funnel_++;
}

void SchedulerStateMachine::DidLoseOutputSurface() {
  if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
      output_surface_state_ == OUTPUT_SURFACE_CREATING)
    return;
  output_surface_state_ = OUTPUT_SURFACE_LOST;
  needs_redraw_ = false;
}

void SchedulerStateMachine::NotifyReadyToActivate() {
  if (has_pending_tree_)
    pending_tree_is_ready_for_activation_ = true;
}

void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
  DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
  output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;

  if (did_create_and_initialize_first_output_surface_) {
    // TODO(boliu): See if we can remove this when impl-side painting is always
    // on. Does anything on the main thread need to update after recreate?
    needs_commit_ = true;
  }
  did_create_and_initialize_first_output_surface_ = true;
  pending_swaps_ = 0;
}

void SchedulerStateMachine::NotifyBeginMainFrameStarted() {
  DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
  commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED;
}

bool SchedulerStateMachine::HasInitializedOutputSurface() const {
  switch (output_surface_state_) {
    case OUTPUT_SURFACE_LOST:
    case OUTPUT_SURFACE_CREATING:
      return false;

    case OUTPUT_SURFACE_ACTIVE:
    case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
    case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
      return true;
  }
  NOTREACHED();
  return false;
}

std::string SchedulerStateMachine::GetStatesForDebugging() const {
  return base::StringPrintf("%c %d %d %d %c %c %c %d %d",
      needs_commit_ ? 'T' : 'F',
      static_cast<int>(output_surface_state_),
      static_cast<int>(begin_impl_frame_state_),
      static_cast<int>(commit_state_),
      has_pending_tree_ ? 'T' : 'F',
      pending_tree_is_ready_for_activation_ ? 'T' : 'F',
      active_tree_needs_first_draw_ ? 'T' : 'F',
      max_pending_swaps_,
      pending_swaps_);
}

}  // namespace cc
