12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2011 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/scheduler/scheduler_state_machine.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
78bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/debug/trace_event.h"
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/debug/trace_event_argument.h"
97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/format_macros.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/values.h"
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ui/gfx/frame_time.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : settings_(settings),
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      output_surface_state_(OUTPUT_SURFACE_LOST),
208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      begin_impl_frame_state_(BEGIN_IMPL_FRAME_STATE_IDLE),
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      commit_state_(COMMIT_STATE_IDLE),
2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      commit_count_(0),
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_frame_number_(0),
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      last_frame_number_animate_performed_(-1),
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      last_frame_number_swap_performed_(-1),
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      last_frame_number_swap_requested_(-1),
288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      last_frame_number_begin_main_frame_sent_(-1),
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      last_frame_number_update_visible_tiles_was_called_(-1),
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      manage_tiles_funnel_(0),
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      consecutive_checkerboard_animations_(0),
320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      max_pending_swaps_(1),
330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      pending_swaps_(0),
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      needs_redraw_(false),
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      needs_animate_(false),
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      needs_manage_tiles_(false),
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      swap_used_incomplete_tile_(false),
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      needs_commit_(false),
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      inside_poll_for_anticipated_draw_triggers_(false),
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      visible_(false),
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      can_start_(false),
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      can_draw_(false),
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      has_pending_tree_(false),
44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      pending_tree_is_ready_for_activation_(false),
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      active_tree_needs_first_draw_(false),
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      did_create_and_initialize_first_output_surface_(false),
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      impl_latency_takes_priority_(false),
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      skip_next_begin_main_frame_to_reduce_latency_(false),
49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      skip_begin_main_frame_to_reduce_latency_(false),
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continuous_painting_(false) {
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
53424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char* SchedulerStateMachine::OutputSurfaceStateToString(
54424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    OutputSurfaceState state) {
55424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  switch (state) {
56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case OUTPUT_SURFACE_ACTIVE:
57424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return "OUTPUT_SURFACE_ACTIVE";
58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case OUTPUT_SURFACE_LOST:
59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return "OUTPUT_SURFACE_LOST";
60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case OUTPUT_SURFACE_CREATING:
61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return "OUTPUT_SURFACE_CREATING";
62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return "OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT";
64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
65424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return "OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION";
66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
67424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  NOTREACHED();
68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return "???";
69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
70424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const char* SchedulerStateMachine::BeginImplFrameStateToString(
728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    BeginImplFrameState state) {
7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  switch (state) {
748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case BEGIN_IMPL_FRAME_STATE_IDLE:
758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return "BEGIN_IMPL_FRAME_STATE_IDLE";
768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING:
778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING";
788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME:
798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME";
808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE:
818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE";
8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  NOTREACHED();
8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return "???";
8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (state) {
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case COMMIT_STATE_IDLE:
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return "COMMIT_STATE_IDLE";
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case COMMIT_STATE_BEGIN_MAIN_FRAME_SENT:
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "COMMIT_STATE_BEGIN_MAIN_FRAME_SENT";
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED:
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED";
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case COMMIT_STATE_READY_TO_COMMIT:
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return "COMMIT_STATE_READY_TO_COMMIT";
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case COMMIT_STATE_WAITING_FOR_ACTIVATION:
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return "COMMIT_STATE_WAITING_FOR_ACTIVATION";
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case COMMIT_STATE_WAITING_FOR_FIRST_DRAW:
1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW";
1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  NOTREACHED();
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return "???";
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const char* SchedulerStateMachine::ForcedRedrawOnTimeoutStateToString(
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ForcedRedrawOnTimeoutState state) {
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  switch (state) {
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case FORCED_REDRAW_STATE_IDLE:
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "FORCED_REDRAW_STATE_IDLE";
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case FORCED_REDRAW_STATE_WAITING_FOR_COMMIT:
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "FORCED_REDRAW_STATE_WAITING_FOR_COMMIT";
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION:
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION";
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case FORCED_REDRAW_STATE_WAITING_FOR_DRAW:
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "FORCED_REDRAW_STATE_WAITING_FOR_DRAW";
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NOTREACHED();
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return "???";
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char* SchedulerStateMachine::ActionToString(Action action) {
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (action) {
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case ACTION_NONE:
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return "ACTION_NONE";
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case ACTION_ANIMATE:
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return "ACTION_ANIMATE";
1288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case ACTION_SEND_BEGIN_MAIN_FRAME:
1298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return "ACTION_SEND_BEGIN_MAIN_FRAME";
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case ACTION_COMMIT:
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return "ACTION_COMMIT";
1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case ACTION_UPDATE_VISIBLE_TILES:
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return "ACTION_UPDATE_VISIBLE_TILES";
134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case ACTION_ACTIVATE_SYNC_TREE:
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return "ACTION_ACTIVATE_SYNC_TREE";
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE";
13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ACTION_DRAW_AND_SWAP_FORCED:
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "ACTION_DRAW_AND_SWAP_FORCED";
1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case ACTION_DRAW_AND_SWAP_ABORT:
1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return "ACTION_DRAW_AND_SWAP_ABORT";
1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION";
144d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    case ACTION_MANAGE_TILES:
145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return "ACTION_MANAGE_TILES";
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  NOTREACHED();
1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return "???";
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_refptr<base::debug::ConvertableToTraceFormat>
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SchedulerStateMachine::AsValue() const {
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<base::debug::TracedValue> state =
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new base::debug::TracedValue();
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AsValueInto(state.get(), gfx::FrameTime::Now());
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return state;
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SchedulerStateMachine::AsValueInto(base::debug::TracedValue* state,
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        base::TimeTicks now) const {
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->BeginDictionary("major_state");
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetString("next_action", ActionToString(NextAction()));
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetString("begin_impl_frame_state",
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   BeginImplFrameStateToString(begin_impl_frame_state_));
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetString("commit_state", CommitStateToString(commit_state_));
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetString("output_surface_state_",
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   OutputSurfaceStateToString(output_surface_state_));
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetString("forced_redraw_state",
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   ForcedRedrawOnTimeoutStateToString(forced_redraw_state_));
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->EndDictionary();
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->BeginDictionary("major_timestamps_in_ms");
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetDouble("0_interval",
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L);
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetDouble(
1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "1_now_to_deadline",
177a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      (begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L);
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetDouble(
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "2_frame_time_to_now",
180a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      (now - begin_impl_frame_args_.frame_time).InMicroseconds() / 1000.0L);
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetDouble("3_frame_time_to_deadline",
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   (begin_impl_frame_args_.deadline -
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    begin_impl_frame_args_.frame_time).InMicroseconds() /
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       1000.0L);
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetDouble("4_now",
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   (now - base::TimeTicks()).InMicroseconds() / 1000.0L);
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetDouble(
1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "5_frame_time",
189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      (begin_impl_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() /
1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          1000.0L);
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetDouble(
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "6_deadline",
193a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      (begin_impl_frame_args_.deadline - base::TimeTicks()).InMicroseconds() /
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          1000.0L);
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->EndDictionary();
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->BeginDictionary("minor_state");
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetInteger("commit_count", commit_count_);
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetInteger("current_frame_number", current_frame_number_);
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetInteger("last_frame_number_animate_performed",
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    last_frame_number_animate_performed_);
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetInteger("last_frame_number_swap_performed",
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    last_frame_number_swap_performed_);
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetInteger("last_frame_number_swap_requested",
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    last_frame_number_swap_requested_);
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetInteger("last_frame_number_begin_main_frame_sent",
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    last_frame_number_begin_main_frame_sent_);
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetInteger("last_frame_number_update_visible_tiles_was_called",
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    last_frame_number_update_visible_tiles_was_called_);
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetInteger("manage_tiles_funnel", manage_tiles_funnel_);
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetInteger("consecutive_checkerboard_animations",
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    consecutive_checkerboard_animations_);
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetInteger("max_pending_swaps_", max_pending_swaps_);
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetInteger("pending_swaps_", pending_swaps_);
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("needs_redraw", needs_redraw_);
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("needs_animate_", needs_animate_);
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("needs_manage_tiles", needs_manage_tiles_);
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("swap_used_incomplete_tile", swap_used_incomplete_tile_);
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("needs_commit", needs_commit_);
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("visible", visible_);
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("can_start", can_start_);
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("can_draw", can_draw_);
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("has_pending_tree", has_pending_tree_);
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("pending_tree_is_ready_for_activation",
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    pending_tree_is_ready_for_activation_);
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("active_tree_needs_first_draw",
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    active_tree_needs_first_draw_);
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("did_create_and_initialize_first_output_surface",
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    did_create_and_initialize_first_output_surface_);
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  state->SetBoolean("impl_latency_takes_priority",
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    impl_latency_takes_priority_);
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("main_thread_is_in_high_latency_mode",
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    MainThreadIsInHighLatencyMode());
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("skip_begin_main_frame_to_reduce_latency",
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    skip_begin_main_frame_to_reduce_latency_);
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency",
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    skip_next_begin_main_frame_to_reduce_latency_);
2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->SetBoolean("continuous_painting", continuous_painting_);
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  state->EndDictionary();
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SchedulerStateMachine::AdvanceCurrentFrameNumber() {
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  current_frame_number_++;
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // "Drain" the ManageTiles funnel.
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (manage_tiles_funnel_ > 0)
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    manage_tiles_funnel_--;
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  skip_begin_main_frame_to_reduce_latency_ =
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      skip_next_begin_main_frame_to_reduce_latency_;
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  skip_next_begin_main_frame_to_reduce_latency_ = false;
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const {
25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return current_frame_number_ ==
2588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)         last_frame_number_begin_main_frame_sent_;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
261ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return current_frame_number_ ==
26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)         last_frame_number_update_visible_tiles_was_called_;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool SchedulerStateMachine::HasSwappedThisFrame() const {
26768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return current_frame_number_ == last_frame_number_swap_performed_;
268558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
269558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool SchedulerStateMachine::HasRequestedSwapThisFrame() const {
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return current_frame_number_ == last_frame_number_swap_requested_;
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // These are all the cases where we normally cannot or do not want to draw
276424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // but, if needs_redraw_ is true and we do not draw to make forward progress,
277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // we might deadlock with the main thread.
278424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // This should be a superset of PendingActivationsShouldBeForced() since
279424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // activation of the pending tree is blocked by drawing of the active tree and
280424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // the main thread might be blocked on activation of the most recent commit.
281424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (PendingActivationsShouldBeForced())
282424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return true;
283424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
284424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Additional states where we should abort draws.
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!can_draw_)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
287424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return false;
288424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
289424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
290424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SchedulerStateMachine::PendingActivationsShouldBeForced() const {
29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // There is no output surface to trigger our activations.
2921675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // If we do not force activations to make forward progress, we might deadlock
2931675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // with the main thread.
29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (output_surface_state_ == OUTPUT_SURFACE_LOST)
295424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return true;
29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2971675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // If we're not visible, we should force activation.
2981675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // Since we set RequiresHighResToDraw when becoming visible, we ensure that we
2991675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // don't checkerboard until all visible resources are done. Furthermore, if we
3001675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // do keep the pending tree around, when becoming visible we might activate
3011675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // prematurely causing RequiresHighResToDraw flag to be reset. In all cases,
3021675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // we can simply activate on becoming invisible since we don't need to draw
3031675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // the active tree when we're in this state.
3041675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  if (!visible_)
3051675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    return true;
3061675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
310424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const {
311424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Don't try to initialize too early.
312424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!can_start_)
313424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
314424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
315424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // We only want to start output surface initialization after the
316424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // previous commit is complete.
317424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (commit_state_ != COMMIT_STATE_IDLE)
318424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
319424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Make sure the BeginImplFrame from any previous OutputSurfaces
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // are complete before creating the new OutputSurface.
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_IDLE)
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // We want to clear the pipline of any pending draws and activations
32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // before starting output surface initialization. This allows us to avoid
32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // weird corner cases where we abort draws or force activation while we
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // are initializing the output surface.
32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (active_tree_needs_first_draw_ || has_pending_tree_)
33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return false;
33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
332424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // We need to create the output surface if we don't have one and we haven't
333424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // started creating one yet.
334424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return output_surface_state_ == OUTPUT_SURFACE_LOST;
335424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
336424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SchedulerStateMachine::ShouldDraw() const {
338424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // If we need to abort draws, we should do so ASAP since the draw could
339424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // be blocking other important actions (like output surface initialization),
340424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // from occuring. If we are waiting for the first draw, then perfom the
341424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // aborted draw to keep things moving. If we are not waiting for the first
342424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // draw however, we don't want to abort for no reason.
343424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (PendingDrawsShouldBeAborted())
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return active_tree_needs_first_draw_;
3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // After this line, we only want to send a swap request once per frame.
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (HasRequestedSwapThisFrame())
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Do not queue too many swaps.
3510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (pending_swaps_ >= max_pending_swaps_)
3520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return false;
3530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Except for the cases above, do not draw outside of the BeginImplFrame
3558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // deadline.
3568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
35958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Only handle forced redraws due to timeouts on the regular deadline.
360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
36158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return true;
36258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return needs_redraw_;
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
366424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SchedulerStateMachine::ShouldActivatePendingTree() const {
367424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // There is nothing to activate.
368424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!has_pending_tree_)
369424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
370424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // We should not activate a second tree before drawing the first one.
37258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Even if we need to force activation of the pending tree, we should abort
37358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // drawing the active tree first.
37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (active_tree_needs_first_draw_)
375424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
376424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
377424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // If we want to force activation, do so ASAP.
378424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (PendingActivationsShouldBeForced())
379424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return true;
380424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
381424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // At this point, only activate if we are ready to activate.
382424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return pending_tree_is_ready_for_activation_;
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
385ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!settings_.impl_side_painting)
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
388ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (HasUpdatedVisibleTilesThisFrame())
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We don't want to update visible tiles right after drawing.
392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (HasRequestedSwapThisFrame())
393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
395424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // There's no reason to check for tiles if we don't have an output surface.
396424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!HasInitializedOutputSurface())
397424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
398424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
39968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // We should not check for visible tiles until we've entered the deadline so
40068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // we check as late as possible and give the tiles more time to initialize.
4018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
40268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
403424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
404424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // If the last swap drew with checkerboard or missing tiles, we should
405424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // poll for any new visible tiles so we can be notified to draw again
406424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // when there are.
407424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (swap_used_incomplete_tile_)
408424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return true;
409424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
410424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return false;
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool SchedulerStateMachine::ShouldAnimate() const {
4145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!can_draw_)
4155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
4165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (last_frame_number_animate_performed_ == current_frame_number_)
4185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
4195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING &&
4215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
4225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
4235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return needs_redraw_ || needs_animate_;
4255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool SchedulerStateMachine::CouldSendBeginMainFrame() const {
428424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!needs_commit_)
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
430424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
4316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // We can not perform commits if we are not visible.
4326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!visible_)
4336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;
4346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return true;
4366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
4376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
4396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!CouldSendBeginMainFrame())
4406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;
4416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Only send BeginMainFrame when there isn't another commit pending already.
443424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (commit_state_ != COMMIT_STATE_IDLE)
444424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
445424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Don't send BeginMainFrame early if we are prioritizing the active tree
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // because of impl_latency_takes_priority_.
4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (impl_latency_takes_priority_ &&
449a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      (has_pending_tree_ || active_tree_needs_first_draw_)) {
450424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
452424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
453424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // We want to start the first commit after we get a new output surface ASAP.
454424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
455424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return true;
456424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We should not send BeginMainFrame while we are in
458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // BEGIN_IMPL_FRAME_STATE_IDLE since we might have new
459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // user input arriving soon.
4608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // TODO(brianderson): Allow sending BeginMainFrame while idle when the main
4618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // thread isn't consuming user input.
462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE &&
463a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      BeginFrameNeeded())
46468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
46568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
46658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // We need a new commit for the forced redraw. This honors the
46758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // single commit per interval because the result will be swapped to screen.
46858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
46958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return true;
47058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
471424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // After this point, we only start a commit once per frame.
4728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (HasSentBeginMainFrameThisFrame())
473424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
474424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
475424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // We shouldn't normally accept commits if there isn't an OutputSurface.
476424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!HasInitializedOutputSurface())
477424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
478424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // SwapAck throttle the BeginMainFrames unless we just swapped.
4800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // TODO(brianderson): Remove this restriction to improve throughput.
481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool just_swapped_in_deadline =
482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      HasSwappedThisFrame();
484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (pending_swaps_ >= max_pending_swaps_ && !just_swapped_in_deadline)
4850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return false;
4860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (skip_begin_main_frame_to_reduce_latency_)
488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
489f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
490424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return true;
491424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
492424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
493424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SchedulerStateMachine::ShouldCommit() const {
494a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (commit_state_ != COMMIT_STATE_READY_TO_COMMIT)
495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We must not finish the commit until the pending tree is free.
498a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (has_pending_tree_) {
499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK(settings_.main_frame_before_activation_enabled);
500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Prioritize drawing the previous commit before finishing the next commit.
504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (active_tree_needs_first_draw_)
505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return true;
508f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
509f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
510d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool SchedulerStateMachine::ShouldManageTiles() const {
511f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // ManageTiles only really needs to be called immediately after commit
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // and then periodically after that. Use a funnel to make sure we average
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // one ManageTiles per BeginImplFrame in the long run.
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (manage_tiles_funnel_ > 0)
515f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
516f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
517d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Limiting to once per-frame is not enough, since we only want to
518d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // manage tiles _after_ draws. Polling for draw triggers and
519d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // begin-frame are mutually exclusive, so we limit to these two cases.
5208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
52168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      !inside_poll_for_anticipated_draw_triggers_)
522d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return false;
523d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return needs_manage_tiles_;
524d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
525d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
527424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (ShouldUpdateVisibleTiles())
528424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return ACTION_UPDATE_VISIBLE_TILES;
529424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (ShouldActivatePendingTree())
530116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return ACTION_ACTIVATE_SYNC_TREE;
531424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (ShouldCommit())
532424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return ACTION_COMMIT;
5335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (ShouldAnimate())
5345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return ACTION_ANIMATE;
535424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (ShouldDraw()) {
536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (PendingDrawsShouldBeAborted())
537424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return ACTION_DRAW_AND_SWAP_ABORT;
53858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
53958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return ACTION_DRAW_AND_SWAP_FORCED;
540424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    else
54158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
543d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (ShouldManageTiles())
544d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return ACTION_MANAGE_TILES;
5458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (ShouldSendBeginMainFrame())
5468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return ACTION_SEND_BEGIN_MAIN_FRAME;
547424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (ShouldBeginOutputSurfaceCreation())
548424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ACTION_NONE;
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SchedulerStateMachine::UpdateState(Action action) {
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (action) {
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ACTION_NONE:
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
557ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    case ACTION_UPDATE_VISIBLE_TILES:
55868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      last_frame_number_update_visible_tiles_was_called_ =
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          current_frame_number_;
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case ACTION_ACTIVATE_SYNC_TREE:
563424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      UpdateStateOnActivation();
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case ACTION_ANIMATE:
5675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      last_frame_number_animate_performed_ = current_frame_number_;
5685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      needs_animate_ = false;
5695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // TODO(skyostil): Instead of assuming this, require the client to tell
5705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // us.
5715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      SetNeedsRedraw();
5725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return;
5735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case ACTION_SEND_BEGIN_MAIN_FRAME:
575a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DCHECK(!has_pending_tree_ ||
576a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             settings_.main_frame_before_activation_enabled);
577a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DCHECK(!active_tree_needs_first_draw_ ||
578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             settings_.main_frame_before_draw_enabled);
579cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DCHECK(visible_);
580a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT;
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      needs_commit_ = false;
5828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      last_frame_number_begin_main_frame_sent_ =
583558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch          current_frame_number_;
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case ACTION_COMMIT: {
5873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      bool commit_was_aborted = false;
588424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      UpdateStateOnCommit(commit_was_aborted);
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
59258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ACTION_DRAW_AND_SWAP_FORCED:
59358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
5940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      bool did_request_swap = true;
5950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      UpdateStateOnDraw(did_request_swap);
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
5973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
5983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case ACTION_DRAW_AND_SWAP_ABORT: {
6000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      bool did_request_swap = false;
6010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      UpdateStateOnDraw(did_request_swap);
6023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return;
6033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      output_surface_state_ = OUTPUT_SURFACE_CREATING;
60858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
60958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // The following DCHECKs make sure we are in the proper quiescent state.
61058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // The pipeline should be flushed entirely before we start output
61158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // surface creation to avoid complicated corner cases.
61258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
61358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      DCHECK(!has_pending_tree_);
61458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      DCHECK(!active_tree_needs_first_draw_);
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
617d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    case ACTION_MANAGE_TILES:
618d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      UpdateStateOnManageTiles();
619d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return;
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
623424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) {
624424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  commit_count_++;
625424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
626a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (commit_was_aborted || settings_.main_frame_before_activation_enabled) {
627a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    commit_state_ = COMMIT_STATE_IDLE;
628a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else if (settings_.main_frame_before_draw_enabled) {
629a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    commit_state_ = settings_.impl_side_painting
630a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        ? COMMIT_STATE_WAITING_FOR_ACTIVATION
631a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        : COMMIT_STATE_IDLE;
632a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else {
633a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
634a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
635a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
636424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // If we are impl-side-painting but the commit was aborted, then we behave
637424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // mostly as if we are not impl-side-painting since there is no pending tree.
638424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  has_pending_tree_ = settings_.impl_side_painting && !commit_was_aborted;
639424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
640cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Update state related to forced draws.
641cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) {
642cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    forced_redraw_state_ = has_pending_tree_
643cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               ? FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
644cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               : FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
64558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
64658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
647cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Update the output surface state.
648cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_NE(output_surface_state_, OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
649cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
650cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (has_pending_tree_) {
651cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
652cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
653cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
654cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      needs_redraw_ = true;
655424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
656424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
657424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
658424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Update state if we have a new active tree to draw, or if the active tree
659cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // was unchanged but we need to do a forced draw.
660424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!has_pending_tree_ &&
66158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      (!commit_was_aborted ||
66258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)       forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)) {
663424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    needs_redraw_ = true;
66458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    active_tree_needs_first_draw_ = true;
665424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
666424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
667424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // This post-commit work is common to both completed and aborted commits.
668424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  pending_tree_is_ready_for_activation_ = false;
669424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
670c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (continuous_painting_)
671c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    needs_commit_ = true;
672424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
673424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
674424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void SchedulerStateMachine::UpdateStateOnActivation() {
675a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (commit_state_ == COMMIT_STATE_WAITING_FOR_ACTIVATION)
676a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    commit_state_ = COMMIT_STATE_IDLE;
677a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
678424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
679424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
680424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
68158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION)
68258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
68358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
684424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  has_pending_tree_ = false;
685424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  pending_tree_is_ready_for_activation_ = false;
68658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  active_tree_needs_first_draw_ = true;
687424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  needs_redraw_ = true;
688424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
689424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
6900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid SchedulerStateMachine::UpdateStateOnDraw(bool did_request_swap) {
691cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
69258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
69358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
694010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!has_pending_tree_ &&
695010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) {
696a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    commit_state_ = COMMIT_STATE_IDLE;
697010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
698a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
6993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  needs_redraw_ = false;
70058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  active_tree_needs_first_draw_ = false;
7013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (did_request_swap)
703cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    last_frame_number_swap_requested_ = current_frame_number_;
7043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
7053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
706d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void SchedulerStateMachine::UpdateStateOnManageTiles() {
707d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  needs_manage_tiles_ = false;
708d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
709d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
710a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() {
711a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  skip_next_begin_main_frame_to_reduce_latency_ = true;
712f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
713f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
714a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool SchedulerStateMachine::BeginFrameNeeded() const {
715a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Proactive BeginFrames are bad for the synchronous compositor because we
716a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // have to draw when we get the BeginFrame and could end up drawing many
71768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // duplicate frames if our new frame isn't ready in time.
71868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // To poll for state with the synchronous compositor without having to draw,
71968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // we rely on ShouldPollForAnticipatedDrawTriggers instead.
720a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!SupportsProactiveBeginFrame())
7215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return BeginFrameNeededToAnimateOrDraw();
72268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return BeginFrameNeededToAnimateOrDraw() || ProactiveBeginFrameWanted();
72468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
72568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
72668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
72768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // ShouldPollForAnticipatedDrawTriggers is what we use in place of
728a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // ProactiveBeginFrameWanted when we are using the synchronous
72968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // compositor.
730a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!SupportsProactiveBeginFrame()) {
7315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return !BeginFrameNeededToAnimateOrDraw() && ProactiveBeginFrameWanted();
73268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
73368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
73468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Non synchronous compositors should rely on
735a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // ProactiveBeginFrameWanted to poll for state instead.
73668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return false;
73768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
73868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Note: If SupportsProactiveBeginFrame is false, the scheduler should poll
7405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// for changes in it's draw state so it can request a BeginFrame when it's
7415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// actually ready.
742a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool SchedulerStateMachine::SupportsProactiveBeginFrame() const {
7435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // It is undesirable to proactively request BeginFrames if we are
7445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // using a synchronous compositor because we *must* draw for every
7455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // BeginFrame, which could cause duplicate draws.
7460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return !settings_.using_synchronous_renderer_compositor;
7474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
7484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
74958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// These are the cases where we definitely (or almost definitely) have a
7505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// new frame to animate and/or draw and can draw.
7515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool SchedulerStateMachine::BeginFrameNeededToAnimateOrDraw() const {
7528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // The output surface is the provider of BeginImplFrames, so we are not going
7538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // to get them even if we ask for them.
75458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!HasInitializedOutputSurface())
75558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return false;
75658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we can't draw, don't tick until we are notified that we can draw again.
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!can_draw_)
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
76158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The forced draw respects our normal draw scheduling, so we need to
7628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // request a BeginImplFrame for it.
76358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
76658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // There's no need to produce frames if we are not visible.
76758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!visible_)
76858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return false;
76958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // We need to draw a more complete frame than we did the last BeginImplFrame,
7718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // so request another BeginImplFrame in anticipation that we will have
77258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // additional visible tiles.
77358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (swap_used_incomplete_tile_)
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (needs_animate_)
7775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return true;
7785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
77958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return needs_redraw_;
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
78258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// These are cases where we are very likely to draw soon, but might not
7838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// actually have a new frame to draw when we receive the next BeginImplFrame.
7848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Proactively requesting the BeginImplFrame helps hide the round trip latency
785a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// of the SetNeedsBeginFrame request that has to go to the Browser.
786a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool SchedulerStateMachine::ProactiveBeginFrameWanted() const {
7878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // The output surface is the provider of BeginImplFrames,
788424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // so we are not going to get them even if we ask for them.
789424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!HasInitializedOutputSurface())
790424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
791424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Do not be proactive when invisible.
793424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!visible_)
794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
7957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
7968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // We should proactively request a BeginImplFrame if a commit is pending
79758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // because we will want to draw if the commit completes quickly.
79858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE)
79958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return true;
80058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // If the pending tree activates quickly, we'll want a BeginImplFrame soon
80258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // to draw the new active tree.
80358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (has_pending_tree_)
80458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return true;
80558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
806d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Changing priorities may allow us to activate (given the new priorities),
807d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // which may result in a new frame.
808d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (needs_manage_tiles_)
809d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return true;
810d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
811cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // If we just sent a swap request, it's likely that we are going to produce
812cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // another frame soon. This helps avoid negative glitches in our
813a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame
8141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // provider and get sampled at an inopportune time, delaying the next
8151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // BeginImplFrame.
816cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (HasRequestedSwapThisFrame())
817d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return true;
818d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
81958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return false;
8207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
8217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
8228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) {
8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AdvanceCurrentFrameNumber();
824a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  begin_impl_frame_args_ = args;
8255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE)
8265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      << AsValue()->ToString();
8278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
82890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() {
8318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK_EQ(begin_impl_frame_state_,
8328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)
8335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      << AsValue()->ToString();
8348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
83568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
83668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SchedulerStateMachine::OnBeginImplFrameDeadline() {
8388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
8395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      << AsValue()->ToString();
8408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
84168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
84268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SchedulerStateMachine::OnBeginImplFrameIdle() {
8448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
8455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      << AsValue()->ToString();
8468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
84768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
84868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const {
8508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // TODO(brianderson): This should take into account multiple commit sources.
8518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
8538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return false;
8548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If we've lost the output surface, end the current BeginImplFrame ASAP
8565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // so we can start creating the next output surface.
8575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (output_surface_state_ == OUTPUT_SURFACE_LOST)
8585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
8595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // SwapAck throttle the deadline since we wont draw and swap anyway.
8610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (pending_swaps_ >= max_pending_swaps_)
8620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return false;
8630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
8648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (active_tree_needs_first_draw_)
8658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return true;
8668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!needs_redraw_)
8681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return false;
8691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
8708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // This is used to prioritize impl-thread draws when the main thread isn't
8718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // producing anything, e.g., after an aborted commit. We also check that we
8728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // don't have a pending tree -- otherwise we should give it a chance to
8738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // activate.
8748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // TODO(skyostil): Revisit this when we have more accurate deadline estimates.
8751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_)
8761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return true;
8771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
8781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Prioritize impl-thread draws in impl_latency_takes_priority_ mode.
8791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (impl_latency_takes_priority_)
8808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return true;
8818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
8828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return false;
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
885f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
886a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // If a commit is pending before the previous commit has been drawn, we
887a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // are definitely in a high latency mode.
888a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (CommitPending() && (active_tree_needs_first_draw_ || has_pending_tree_))
889a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return true;
890a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
891f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main
892f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // thread is in a low latency mode.
893cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (HasSentBeginMainFrameThisFrame() &&
894f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING ||
895f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME))
896f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
897f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
898f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // If there's a commit in progress it must either be from the previous frame
899f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // or it started after the impl thread's deadline. In either case the main
900f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // thread is in high latency mode.
901cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (CommitPending())
902f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return true;
903f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
904f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Similarly, if there's a pending tree the main thread is in high latency
905f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // mode, because either
906f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  //   it's from the previous frame
907f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // or
908f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  //   we're currently drawing the active tree and the pending tree will thus
909f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  //   only be drawn in the next frame.
910f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (has_pending_tree_)
911f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return true;
912f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
913f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
914f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Even if there's a new active tree to draw at the deadline or we've just
915cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // swapped it, it may have been triggered by a previous BeginImplFrame, in
916f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // which case the main thread is in a high latency mode.
917cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return (active_tree_needs_first_draw_ || HasSwappedThisFrame()) &&
918cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)           !HasSentBeginMainFrameThisFrame();
919f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
920f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
921f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // If the active tree needs its first draw in any other state, we know the
922f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // main thread is in a high latency mode.
923f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return active_tree_needs_first_draw_;
924f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
925f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
926d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AdvanceCurrentFrameNumber();
928d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  inside_poll_for_anticipated_draw_triggers_ = true;
929d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
930d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
931d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() {
932d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  inside_poll_for_anticipated_draw_triggers_ = false;
93358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
93458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
93768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
93868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid SchedulerStateMachine::SetNeedsAnimate() {
9425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  needs_animate_ = true;
9435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
9445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
945d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void SchedulerStateMachine::SetNeedsManageTiles() {
9468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!needs_manage_tiles_) {
9478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    TRACE_EVENT0("cc",
9488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                 "SchedulerStateMachine::SetNeedsManageTiles");
9498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    needs_manage_tiles_ = true;
9508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
951d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
952d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
9530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid SchedulerStateMachine::SetMaxSwapsPending(int max) {
9540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  max_pending_swaps_ = max;
9550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
9560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
9570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid SchedulerStateMachine::DidSwapBuffers() {
9580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  pending_swaps_++;
9590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK_LE(pending_swaps_, max_pending_swaps_);
960cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
961cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  last_frame_number_swap_performed_ = current_frame_number_;
9620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
9630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
96458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void SchedulerStateMachine::SetSwapUsedIncompleteTile(
96558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    bool used_incomplete_tile) {
96658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  swap_used_incomplete_tile_ = used_incomplete_tile;
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid SchedulerStateMachine::DidSwapBuffersComplete() {
9700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK_GT(pending_swaps_, 0);
9710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  pending_swaps_--;
9720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
9730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
9741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SchedulerStateMachine::SetImplLatencyTakesPriority(
9751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool impl_latency_takes_priority) {
9761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  impl_latency_takes_priority_ = impl_latency_takes_priority;
9771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
9781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
979cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SchedulerStateMachine::DidDrawIfPossibleCompleted(DrawResult result) {
9805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (result) {
981cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case INVALID_RESULT:
982cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      NOTREACHED() << "Uninitialized DrawResult.";
9835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
984cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case DRAW_ABORTED_CANT_DRAW:
985cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case DRAW_ABORTED_CONTEXT_LOST:
9865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NOTREACHED() << "Invalid return value from DrawAndSwapIfPossible:"
9875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   << result;
9885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
989cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case DRAW_SUCCESS:
9905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      consecutive_checkerboard_animations_ = 0;
9915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
9925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
993cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case DRAW_ABORTED_CHECKERBOARD_ANIMATIONS:
9945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      needs_redraw_ = true;
9955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // If we're already in the middle of a redraw, we don't need to
9975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // restart it.
9985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
9995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return;
10005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      needs_commit_ = true;
10025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      consecutive_checkerboard_animations_++;
10035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (settings_.timeout_and_draw_when_animation_checkerboards &&
10045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          consecutive_checkerboard_animations_ >=
10055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              settings_.maximum_number_of_failed_draws_before_draw_is_forced_) {
10065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        consecutive_checkerboard_animations_ = 0;
10075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // We need to force a draw, but it doesn't make sense to do this until
10085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // we've committed and have new textures.
10095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
10105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
10115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
1012cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case DRAW_ABORTED_MISSING_HIGH_RES_CONTENT:
10135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // It's not clear whether this missing content is because of missing
10145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // pictures (which requires a commit) or because of memory pressure
10155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // removing textures (which might not).  To be safe, request a commit
10165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // anyway.
10175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      needs_commit_ = true;
10185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
10192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void SchedulerStateMachine::SetNeedsCommit() {
10236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  needs_commit_ = true;
10246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
10252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1026a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SchedulerStateMachine::NotifyReadyToCommit() {
10275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED)
10285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      << AsValue()->ToString();
10292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SchedulerStateMachine::BeginMainFrameAborted(bool did_handle) {
1033a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
10343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (did_handle) {
10353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    bool commit_was_aborted = true;
1036424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    UpdateStateOnCommit(commit_was_aborted);
10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    commit_state_ = COMMIT_STATE_IDLE;
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetNeedsCommit();
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1043f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SchedulerStateMachine::DidManageTiles() {
1044f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  needs_manage_tiles_ = false;
10455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // "Fill" the ManageTiles funnel.
10465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  manage_tiles_funnel_++;
1047f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1048f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SchedulerStateMachine::DidLoseOutputSurface() {
10502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
1051c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      output_surface_state_ == OUTPUT_SURFACE_CREATING)
10522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  output_surface_state_ = OUTPUT_SURFACE_LOST;
1054424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  needs_redraw_ = false;
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1057424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void SchedulerStateMachine::NotifyReadyToActivate() {
1058424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (has_pending_tree_)
1059424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    pending_tree_is_ready_for_activation_ = true;
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
1063c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
1064424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;
1065c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1066c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (did_create_and_initialize_first_output_surface_) {
1067c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // TODO(boliu): See if we can remove this when impl-side painting is always
1068c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // on. Does anything on the main thread need to update after recreate?
1069a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    needs_commit_ = true;
1070c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1071c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  did_create_and_initialize_first_output_surface_ = true;
10720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  pending_swaps_ = 0;
1073c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1074c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1075a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SchedulerStateMachine::NotifyBeginMainFrameStarted() {
1076a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
1077a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED;
1078a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
1079a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1080c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool SchedulerStateMachine::HasInitializedOutputSurface() const {
1081424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  switch (output_surface_state_) {
1082424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case OUTPUT_SURFACE_LOST:
1083424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case OUTPUT_SURFACE_CREATING:
1084424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return false;
1085424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1086424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case OUTPUT_SURFACE_ACTIVE:
1087424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
1088424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
1089424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return true;
1090424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
1091424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  NOTREACHED();
1092424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return false;
10932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string SchedulerStateMachine::GetStatesForDebugging() const {
10961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return base::StringPrintf("%c %d %d %d %c %c %c %d %d",
10971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      needs_commit_ ? 'T' : 'F',
10981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      static_cast<int>(output_surface_state_),
10991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      static_cast<int>(begin_impl_frame_state_),
11001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      static_cast<int>(commit_state_),
11011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      has_pending_tree_ ? 'T' : 'F',
11021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      pending_tree_is_ready_for_activation_ ? 'T' : 'F',
11031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      active_tree_needs_first_draw_ ? 'T' : 'F',
11041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      max_pending_swaps_,
11051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      pending_swaps_);
11061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
11071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
11082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
1109