1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127

cc / metrics / frame_info.h [blame]

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

#ifndef CC_METRICS_FRAME_INFO_H_
#define CC_METRICS_FRAME_INFO_H_

#include "base/time/time.h"
#include "cc/cc_export.h"

namespace cc {

struct CC_EXPORT FrameInfo {
  FrameInfo();
  FrameInfo(const FrameInfo& other);
  ~FrameInfo();

  enum class FrameFinalState {
    kNoUpdateDesired,
    kDropped,

    // A `presented all` frame contains all the desired update for this vsync.
    // Note that this doesn't necessarily mean the frame included updates from
    // both the main and the compositor thread. For example, if there's only a
    // main-thread animation running, and the animation update was included in
    // the frame produced, then it's `presented all`, although the compositor
    // thread did not have any updates for this frame.
    kPresentedAll,

    // A `partial update` frame contains updates from a compositor frame, but
    // misses the update from the main-thread for the same vsync. However, it is
    // still possible for such a `partial update` frame to contain new update
    // from an earlier main-thread.
    //
    // `kPresentedPartialOldMain` represents a partial update frame without any
    //     new update from the main-thread.
    // `kPresentedPartialNewMain` represents a partial update frame with some
    //     new update from the main-thread.
    kPresentedPartialOldMain,
    kPresentedPartialNewMain,
  };
  FrameFinalState final_state = FrameFinalState::kNoUpdateDesired;
  FrameFinalState final_state_raster_property =
      FrameFinalState::kNoUpdateDesired;
  FrameFinalState final_state_raster_scroll = FrameFinalState::kNoUpdateDesired;

  enum class SmoothThread {
    kSmoothNone,
    kSmoothRaster,
    kSmoothCompositor,
    kSmoothMain,
    kSmoothBoth
  };
  SmoothThread smooth_thread = SmoothThread::kSmoothNone;
  SmoothThread smooth_thread_raster_property = SmoothThread::kSmoothNone;

  enum class MainThreadResponse {
    kIncluded,
    kMissing,
  };
  MainThreadResponse main_thread_response = MainThreadResponse::kIncluded;

  enum class SmoothEffectDrivingThread {
    kMain = 0,
    kCompositor = 1,
    kRaster = 2,
    kUnknown = 3,
    kMaxValue = kUnknown,
  };
  SmoothEffectDrivingThread scroll_thread = SmoothEffectDrivingThread::kUnknown;

  bool checkerboarded_needs_raster = false;
  bool checkerboarded_needs_record = false;
  bool did_raster_inducing_scroll = false;

  // The time when the frame was terminated. If the frame had to be 'split'
  // (i.e. compositor-thread update and main-thread updates were presented in
  // separate frames,) then this contains the maximum time when the updates were
  // terminated. See GetTerminationTimeForThread to get the value for each.
  base::TimeTicks termination_time;

  // The frame number associated to the viz::BeginFrameArgs that started this
  // frame's production.
  uint64_t sequence_number = 0u;

  bool IsDroppedAffectingSmoothness() const;
  void MergeWith(const FrameInfo& info);

  bool Validate() const;

  // Returns whether any update from the compositor/main thread was dropped, and
  // whether the update was part of a smooth sequence.
  bool WasSmoothCompositorUpdateDropped() const;
  bool WasSmoothRasterPropertyUpdateDropped() const;
  bool WasSmoothRasterScrollUpdateDropped() const;
  bool WasSmoothMainUpdateDropped() const;
  bool WasSmoothMainUpdateExpected() const;

  bool IsScrollPrioritizeFrameDropped() const;

  // If this `was_merged` these return the value for `thread`, otherwise returns
  // the default non-merged values.
  FrameFinalState GetFinalStateForThread(
      SmoothEffectDrivingThread thread) const;
  base::TimeTicks GetTerminationTimeForThread(
      SmoothEffectDrivingThread thread) const;

 private:
  bool was_merged = false;
  bool compositor_update_was_dropped = false;
  bool raster_property_was_dropped = false;
  bool raster_scroll_was_dropped = false;
  bool main_update_was_dropped = false;

  // A frame that `was_merged` could have differing final states, and differing
  // termination times. We track both so that each thread's jank can be
  // calculated.
  FrameFinalState compositor_final_state = FrameFinalState::kNoUpdateDesired;
  FrameFinalState main_final_state = FrameFinalState::kNoUpdateDesired;

  base::TimeTicks compositor_termination_time;
  base::TimeTicks main_termination_time;
};

}  // namespace cc

#endif  // CC_METRICS_FRAME_INFO_H_