1 // Copyright 2019 The Chromium Authors. All rights reserved.
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_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_
6 #define CC_METRICS_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_
7 
8 #include <memory>
9 #include <vector>
10 
11 #include "base/time/default_tick_clock.h"
12 #include "base/time/time.h"
13 #include "cc/cc_export.h"
14 #include "cc/metrics/compositor_frame_reporter.h"
15 #include "cc/metrics/event_metrics.h"
16 #include "cc/metrics/frame_sequence_metrics.h"
17 
18 namespace viz {
19 struct FrameTimingDetails;
20 }
21 
22 namespace cc {
23 class DroppedFrameCounter;
24 class UkmManager;
25 struct BeginMainFrameMetrics;
26 
27 // This is used for managing simultaneous CompositorFrameReporter instances
28 // in the case that the compositor has high latency. Calling one of the
29 // event functions will begin recording the time of the corresponding
30 // phase and trace it. If the frame is eventually submitted, then the
31 // recorded times of each phase will be reported in UMA.
32 // See CompositorFrameReporter.
33 class CC_EXPORT CompositorFrameReportingController {
34  public:
35   // Used as indices for accessing CompositorFrameReporters.
36   enum PipelineStage {
37     kBeginImplFrame = 0,
38     kBeginMainFrame,
39     kCommit,
40     kActivate,
41     kNumPipelineStages
42   };
43 
44   CompositorFrameReportingController(bool should_report_metrics,
45                                      int layer_tree_host_id);
46   virtual ~CompositorFrameReportingController();
47 
48   CompositorFrameReportingController(
49       const CompositorFrameReportingController&) = delete;
50   CompositorFrameReportingController& operator=(
51       const CompositorFrameReportingController&) = delete;
52 
53   // Events to signal Beginning/Ending of phases.
54   virtual void WillBeginImplFrame(const viz::BeginFrameArgs& args);
55   virtual void WillBeginMainFrame(const viz::BeginFrameArgs& args);
56   virtual void BeginMainFrameAborted(const viz::BeginFrameId& id);
57   virtual void WillInvalidateOnImplSide();
58   virtual void WillCommit();
59   virtual void DidCommit();
60   virtual void WillActivate();
61   virtual void DidActivate();
62   virtual void DidSubmitCompositorFrame(
63       uint32_t frame_token,
64       const viz::BeginFrameId& current_frame_id,
65       const viz::BeginFrameId& last_activated_frame_id,
66       EventMetricsSet events_metrics);
67   virtual void DidNotProduceFrame(const viz::BeginFrameId& id,
68                                   FrameSkippedReason skip_reason);
69   virtual void OnFinishImplFrame(const viz::BeginFrameId& id);
70   virtual void DidPresentCompositorFrame(
71       uint32_t frame_token,
72       const viz::FrameTimingDetails& details);
73   void OnStoppedRequestingBeginFrames();
74 
75   void SetBlinkBreakdown(std::unique_ptr<BeginMainFrameMetrics> details,
76                          base::TimeTicks main_thread_start_time);
77 
78   void SetUkmManager(UkmManager* manager);
79 
80   void AddActiveTracker(FrameSequenceTrackerType type);
81   void RemoveActiveTracker(FrameSequenceTrackerType type);
82 
83   void SetThreadAffectsSmoothness(FrameSequenceMetrics::ThreadType thread_type,
84                                   bool affects_smoothness);
85 
set_tick_clock(const base::TickClock * tick_clock)86   void set_tick_clock(const base::TickClock* tick_clock) {
87     DCHECK(tick_clock);
88     tick_clock_ = tick_clock;
89   }
90 
reporters()91   std::unique_ptr<CompositorFrameReporter>* reporters() { return reporters_; }
92 
SetDroppedFrameCounter(DroppedFrameCounter * counter)93   void SetDroppedFrameCounter(DroppedFrameCounter* counter) {
94     dropped_frame_counter_ = counter;
95   }
96 
97  protected:
98   struct SubmittedCompositorFrame {
99     uint32_t frame_token;
100     std::unique_ptr<CompositorFrameReporter> reporter;
101     SubmittedCompositorFrame();
102     SubmittedCompositorFrame(uint32_t frame_token,
103                              std::unique_ptr<CompositorFrameReporter> reporter);
104     SubmittedCompositorFrame(SubmittedCompositorFrame&& other);
105     ~SubmittedCompositorFrame();
106   };
107   base::TimeTicks Now() const;
108 
109   bool HasReporterAt(PipelineStage stage) const;
next_activate_has_invalidation()110   bool next_activate_has_invalidation() const {
111     return next_activate_has_invalidation_;
112   }
113 
114  private:
115   void AdvanceReporterStage(PipelineStage start, PipelineStage target);
116   bool CanSubmitImplFrame(const viz::BeginFrameId& id) const;
117   bool CanSubmitMainFrame(const viz::BeginFrameId& id) const;
118   std::unique_ptr<CompositorFrameReporter> RestoreReporterAtBeginImpl(
119       const viz::BeginFrameId& id);
120   CompositorFrameReporter::SmoothThread GetSmoothThread() const;
121 
122   // If the display-compositor skips over some frames (e.g. when the gpu is
123   // busy, or the client is non-responsive), then it will not issue any
124   // |BeginFrameArgs| for those frames. However, |CompositorFrameReporter|
125   // instances should still be created for these frames. The following
126   // functions accomplish this.
127   void ProcessSkippedFramesIfNecessary(const viz::BeginFrameArgs& args);
128   void CreateReportersForDroppedFrames(
129       const viz::BeginFrameArgs& old_args,
130       const viz::BeginFrameArgs& new_args) const;
131 
132   const bool should_report_metrics_;
133   const int layer_tree_host_id_;
134 
135   viz::BeginFrameId last_submitted_frame_id_;
136 
137   bool next_activate_has_invalidation_ = false;
138   CompositorFrameReporter::ActiveTrackers active_trackers_;
139 
140   bool is_compositor_thread_driving_smoothness_ = false;
141   bool is_main_thread_driving_smoothness_ = false;
142 
143   // The latency reporter passed to each CompositorFrameReporter. Owned here
144   // because it must be common among all reporters.
145   // DO NOT reorder this line and the ones below. The latency_ukm_reporter_ must
146   // outlive the objects in |submitted_compositor_frames_|.
147   std::unique_ptr<LatencyUkmReporter> latency_ukm_reporter_;
148 
149   std::unique_ptr<CompositorFrameReporter>
150       reporters_[PipelineStage::kNumPipelineStages];
151 
152   // Mapping of frame token to pipeline reporter for submitted compositor
153   // frames.
154   // DO NOT reorder this line and the one above. The latency_ukm_reporter_ must
155   // outlive the objects in |submitted_compositor_frames_|.
156   base::circular_deque<SubmittedCompositorFrame> submitted_compositor_frames_;
157 
158   // The latest frame that was started.
159   viz::BeginFrameArgs previous_frame_;
160 
161   const base::TickClock* tick_clock_ = base::DefaultTickClock::GetInstance();
162 
163   DroppedFrameCounter* dropped_frame_counter_ = nullptr;
164 };
165 }  // namespace cc
166 
167 #endif  // CC_METRICS_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_
168