[M108 Migration][VD] Avoid pending frame counter becoming negative
[platform/framework/web/chromium-efl.git] / cc / metrics / frame_sequence_metrics.h
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef CC_METRICS_FRAME_SEQUENCE_METRICS_H_
6 #define CC_METRICS_FRAME_SEQUENCE_METRICS_H_
7
8 #include <bitset>
9 #include <cmath>
10 #include <memory>
11
12 #include "base/callback.h"
13 #include "base/check.h"
14 #include "base/memory/raw_ptr.h"
15 #include "base/trace_event/traced_value.h"
16 #include "cc/cc_export.h"
17 #include "cc/metrics/frame_info.h"
18
19 namespace viz {
20 struct BeginFrameArgs;
21 }  // namespace viz
22
23 namespace cc {
24 class ThroughputUkmReporter;
25 class JankMetrics;
26 struct FrameInfo;
27
28 enum class FrameSequenceTrackerType {
29   // Used as an enum for metrics. DO NOT reorder or delete values. Rather,
30   // add them at the end and increment kMaxType.
31   kCompositorAnimation = 0,
32   kMainThreadAnimation = 1,
33   kPinchZoom = 2,
34   kRAF = 3,
35   kTouchScroll = 4,
36   kVideo = 6,
37   kWheelScroll = 7,
38   kScrollbarScroll = 8,
39   kCustom = 9,  // Note that the metrics for kCustom are not reported on UMA,
40                 // and instead are dispatched back to the LayerTreeHostClient.
41   kCanvasAnimation = 10,
42   kJSAnimation = 11,
43   kSETMainThreadAnimation = 12,
44   kSETCompositorAnimation = 13,
45   kMaxType
46 };
47
48 using ActiveTrackers =
49     std::bitset<static_cast<size_t>(FrameSequenceTrackerType::kMaxType)>;
50
51 inline bool IsScrollActive(const ActiveTrackers& trackers) {
52   return trackers.test(
53              static_cast<size_t>(FrameSequenceTrackerType::kWheelScroll)) ||
54          trackers.test(
55              static_cast<size_t>(FrameSequenceTrackerType::kTouchScroll)) ||
56          trackers.test(
57              static_cast<size_t>(FrameSequenceTrackerType::kScrollbarScroll));
58 }
59
60 inline bool HasMainThreadAnimation(const ActiveTrackers& trackers) {
61   return trackers.test(static_cast<size_t>(
62              FrameSequenceTrackerType::kMainThreadAnimation)) ||
63          trackers.test(
64              static_cast<size_t>(FrameSequenceTrackerType::kCanvasAnimation)) ||
65          trackers.test(
66              static_cast<size_t>(FrameSequenceTrackerType::kJSAnimation)) ||
67          trackers.test(static_cast<size_t>(FrameSequenceTrackerType::kRAF));
68 }
69
70 inline bool HasCompositorThreadAnimation(const ActiveTrackers& trackers) {
71   return trackers.test(
72       static_cast<size_t>(FrameSequenceTrackerType::kCompositorAnimation));
73 }
74
75 class CC_EXPORT FrameSequenceMetrics {
76  public:
77   FrameSequenceMetrics(FrameSequenceTrackerType type,
78                        ThroughputUkmReporter* ukm_reporter);
79   ~FrameSequenceMetrics();
80
81   FrameSequenceMetrics(const FrameSequenceMetrics&) = delete;
82   FrameSequenceMetrics& operator=(const FrameSequenceMetrics&) = delete;
83
84   struct ThroughputData {
85     static std::unique_ptr<base::trace_event::TracedValue> ToTracedValue(
86         const ThroughputData& impl,
87         const ThroughputData& main,
88         FrameInfo::SmoothEffectDrivingThread effective_thred);
89
90     static bool CanReportHistogram(
91         FrameSequenceMetrics* metrics,
92         FrameInfo::SmoothEffectDrivingThread thread_type,
93         const ThroughputData& data);
94
95     // Returns the dropped throughput in percent
96     static int ReportDroppedFramePercentHistogram(
97         FrameSequenceMetrics* metrics,
98         FrameInfo::SmoothEffectDrivingThread thread_type,
99         int metric_index,
100         const ThroughputData& data);
101
102     // Returns the missed deadline throughput in percent
103     static int ReportMissedDeadlineFramePercentHistogram(
104         FrameSequenceMetrics* metrics,
105         FrameInfo::SmoothEffectDrivingThread thread_type,
106         int metric_index,
107         const ThroughputData& data);
108
109     static void ReportCheckerboardingHistogram(
110         FrameSequenceMetrics* metrics,
111         FrameInfo::SmoothEffectDrivingThread thread_type,
112         int percent);
113
114     void Merge(const ThroughputData& data) {
115       frames_expected += data.frames_expected;
116       frames_produced += data.frames_produced;
117       frames_ontime += data.frames_ontime;
118 #if DCHECK_IS_ON()
119       frames_processed += data.frames_processed;
120       frames_received += data.frames_received;
121 #endif
122     }
123
124     int DroppedFramePercent() const {
125       if (frames_expected == 0)
126         return 0;
127       return std::ceil(100 * (frames_expected - frames_produced) /
128                        static_cast<double>(frames_expected));
129     }
130
131     int MissedDeadlineFramePercent() const {
132       if (frames_produced == 0)
133         return 0;
134       return std::ceil(100 * (frames_produced - frames_ontime) /
135                        static_cast<double>(frames_produced));
136     }
137
138     // Tracks the number of frames that were expected to be shown during this
139     // frame-sequence.
140     uint32_t frames_expected = 0;
141
142     // Tracks the number of frames that were actually presented to the user
143     // during this frame-sequence.
144     uint32_t frames_produced = 0;
145
146     // Tracks the number of frames that were actually presented to the user
147     // that didn't miss the vsync deadline during this frame-sequence.
148     uint32_t frames_ontime = 0;
149
150 #if DCHECK_IS_ON()
151     // Tracks the number of frames that is either submitted or reported as no
152     // damage.
153     uint32_t frames_processed = 0;
154
155     // Tracks the number of begin-frames that are received.
156     uint32_t frames_received = 0;
157 #endif
158   };
159
160   void SetScrollingThread(FrameInfo::SmoothEffectDrivingThread thread);
161
162   struct CustomReportData {
163     uint32_t frames_expected = 0;
164     uint32_t frames_produced = 0;
165     int jank_count = 0;
166   };
167   using CustomReporter = base::OnceCallback<void(const CustomReportData& data)>;
168   // Sets reporter callback for kCustom typed sequence.
169   void SetCustomReporter(CustomReporter custom_reporter);
170
171   // Returns the 'effective thread' for the metrics (i.e. the thread most
172   // relevant for this metric).
173   FrameInfo::SmoothEffectDrivingThread GetEffectiveThread() const;
174
175   void Merge(std::unique_ptr<FrameSequenceMetrics> metrics);
176   bool HasEnoughDataForReporting() const;
177   bool HasDataLeftForReporting() const;
178   // Report related metrics: throughput, checkboarding...
179   void ReportMetrics();
180
181   void AddSortedFrame(const viz::BeginFrameArgs& args,
182                       const FrameInfo& frame_info);
183
184   ThroughputData& impl_throughput() { return impl_throughput_; }
185   ThroughputData& main_throughput() { return main_throughput_; }
186   void add_checkerboarded_frames(int64_t frames) {
187     frames_checkerboarded_ += frames;
188   }
189   uint32_t frames_checkerboarded() const { return frames_checkerboarded_; }
190
191   FrameSequenceTrackerType type() const { return type_; }
192   ThroughputUkmReporter* ukm_reporter() const {
193     return throughput_ukm_reporter_;
194   }
195
196   // Must be called before destructor.
197   void ReportLeftoverData();
198
199   void AdoptTrace(FrameSequenceMetrics* adopt_from);
200   void AdvanceTrace(base::TimeTicks timestamp);
201
202   void ComputeJank(FrameInfo::SmoothEffectDrivingThread thread_type,
203                    uint32_t frame_token,
204                    base::TimeTicks presentation_time,
205                    base::TimeDelta frame_interval);
206
207   void NotifySubmitForJankReporter(
208       FrameInfo::SmoothEffectDrivingThread thread_type,
209       uint32_t frame_token,
210       uint32_t sequence_number);
211
212   void NotifyNoUpdateForJankReporter(
213       FrameInfo::SmoothEffectDrivingThread thread_type,
214       uint32_t sequence_number,
215       base::TimeDelta frame_interval);
216
217  private:
218   const FrameSequenceTrackerType type_;
219
220   // Tracks some data to generate useful trace events.
221   struct TraceData {
222     explicit TraceData(FrameSequenceMetrics* metrics);
223     ~TraceData();
224     raw_ptr<FrameSequenceMetrics> metrics;
225     base::TimeTicks last_timestamp = base::TimeTicks::Now();
226     int frame_count = 0;
227     bool enabled = false;
228     raw_ptr<void> trace_id = nullptr;
229
230     void Advance(base::TimeTicks new_timestamp,
231                  uint32_t expected,
232                  uint32_t dropped);
233     void Terminate();
234   } trace_data_{this};
235
236   // Pointer to the reporter owned by the FrameSequenceTrackerCollection.
237   const raw_ptr<ThroughputUkmReporter> throughput_ukm_reporter_;
238
239   // Track state for measuring the PercentDroppedFrames v2 metrics.
240   struct {
241     uint32_t frames_expected = 0;
242     uint32_t frames_dropped = 0;
243   } v2_;
244
245   // Track state for measuring the PercentDroppedFrames v3 metrics.
246   struct {
247     uint32_t frames_expected = 0;
248     uint32_t frames_dropped = 0;
249   } v3_;
250
251   ThroughputData impl_throughput_;
252   ThroughputData main_throughput_;
253
254   FrameInfo::SmoothEffectDrivingThread scrolling_thread_ =
255       FrameInfo::SmoothEffectDrivingThread::kUnknown;
256
257   // Tracks the number of produced frames that had some amount of
258   // checkerboarding, and how many frames showed such checkerboarded frames.
259   uint32_t frames_checkerboarded_ = 0;
260
261   // Callback invoked to report metrics for kCustom typed sequence.
262   CustomReporter custom_reporter_;
263
264   std::unique_ptr<JankMetrics> jank_reporter_;
265 };
266
267 bool ShouldReportForAnimation(FrameSequenceTrackerType sequence_type,
268                               FrameInfo::SmoothEffectDrivingThread thread_type);
269
270 bool ShouldReportForInteraction(
271     FrameSequenceTrackerType sequence_type,
272     FrameInfo::SmoothEffectDrivingThread reporting_thread_type,
273     FrameInfo::SmoothEffectDrivingThread metrics_effective_thread_type);
274
275 }  // namespace cc
276
277 #endif  // CC_METRICS_FRAME_SEQUENCE_METRICS_H_