#ifndef CC_METRICS_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_
#define CC_METRICS_COMPOSITOR_FRAME_REPORTING_CONTROLLER_H_
#include <map>
#include <memory>
#include <queue>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "cc/cc_export.h"
#include "cc/metrics/compositor_frame_reporter.h"
#include "cc/metrics/event_metrics.h"
#include "cc/metrics/frame_sequence_metrics.h"
#include "cc/metrics/predictor_jank_tracker.h"
namespace viz {
struct FrameTimingDetails;
}
namespace cc {
class DroppedFrameCounter;
class EventLatencyTracker;
class UkmManager;
struct BeginMainFrameMetrics;
struct FrameInfo;
class CC_EXPORT CompositorFrameReportingController {
public:
enum PipelineStage {
kBeginImplFrame = 0,
kBeginMainFrame,
kReadyToCommit,
kCommit,
kActivate,
kNumPipelineStages
};
CompositorFrameReportingController(bool should_report_histograms,
bool should_report_ukm,
int layer_tree_host_id);
virtual ~CompositorFrameReportingController();
CompositorFrameReportingController(
const CompositorFrameReportingController&) = delete;
CompositorFrameReportingController& operator=(
const CompositorFrameReportingController&) = delete;
virtual void WillBeginImplFrame(const viz::BeginFrameArgs& args);
virtual void WillBeginMainFrame(const viz::BeginFrameArgs& args);
virtual void BeginMainFrameAborted(const viz::BeginFrameId& id,
CommitEarlyOutReason reason);
virtual void WillInvalidateOnImplSide();
virtual void WillCommit();
virtual void DidCommit();
virtual void WillActivate();
virtual void DidActivate();
virtual void DidSubmitCompositorFrame(
uint32_t frame_token,
base::TimeTicks submit_time,
const viz::BeginFrameId& current_frame_id,
const viz::BeginFrameId& last_activated_frame_id,
EventMetricsSet events_metrics,
bool has_missing_content);
virtual void DidNotProduceFrame(const viz::BeginFrameId& id,
FrameSkippedReason skip_reason);
virtual void OnFinishImplFrame(const viz::BeginFrameId& id);
virtual void DidPresentCompositorFrame(
uint32_t frame_token,
const viz::FrameTimingDetails& details);
void OnStoppedRequestingBeginFrames();
void NotifyReadyToCommit(std::unique_ptr<BeginMainFrameMetrics> details);
void SetUkmManager(UkmManager* manager);
void AddActiveTracker(FrameSequenceTrackerType type);
void RemoveActiveTracker(FrameSequenceTrackerType type);
void SetScrollingThread(FrameInfo::SmoothEffectDrivingThread thread);
void SetThreadAffectsSmoothness(
FrameInfo::SmoothEffectDrivingThread thread_type,
bool affects_smoothness);
bool is_main_thread_driving_smoothness() const {
return is_main_thread_driving_smoothness_;
}
void set_tick_clock(const base::TickClock* tick_clock) {
DCHECK(tick_clock);
tick_clock_ = tick_clock;
}
std::unique_ptr<CompositorFrameReporter>* reporters() { return reporters_; }
void SetDroppedFrameCounter(DroppedFrameCounter* counter);
void SetFrameSequenceTrackerCollection(
FrameSequenceTrackerCollection* frame_sequence_trackers) {
global_trackers_.frame_sequence_trackers = frame_sequence_trackers;
}
void set_event_latency_tracker(EventLatencyTracker* event_latency_tracker) {
global_trackers_.event_latency_tracker = event_latency_tracker;
}
void BeginMainFrameStarted(base::TimeTicks begin_main_frame_start_time) {
begin_main_frame_start_time_ = begin_main_frame_start_time;
}
bool HasReporterAt(PipelineStage stage) const;
void SetVisible(bool visible);
protected:
struct SubmittedCompositorFrame {
uint32_t frame_token;
std::unique_ptr<CompositorFrameReporter> reporter;
SubmittedCompositorFrame();
SubmittedCompositorFrame(uint32_t frame_token,
std::unique_ptr<CompositorFrameReporter> reporter);
SubmittedCompositorFrame(SubmittedCompositorFrame&& other);
~SubmittedCompositorFrame();
};
base::TimeTicks Now() const;
bool next_activate_has_invalidation() const {
return next_activate_has_invalidation_;
}
private:
void AdvanceReporterStage(PipelineStage start, PipelineStage target);
bool CanSubmitImplFrame(const viz::BeginFrameId& id) const;
bool CanSubmitMainFrame(const viz::BeginFrameId& id) const;
std::unique_ptr<CompositorFrameReporter> RestoreReporterAtBeginImpl(
const viz::BeginFrameId& id);
CompositorFrameReporter::SmoothThread GetSmoothThread() const;
CompositorFrameReporter::SmoothThread GetSmoothThreadAtTime(
base::TimeTicks timestamp) const;
CompositorFrameReporter* GetOutstandingUpdatesFromMain(
const viz::BeginFrameId& id) const;
void ProcessSkippedFramesIfNecessary(const viz::BeginFrameArgs& args);
void CreateReportersForDroppedFrames(
const viz::BeginFrameArgs& old_args,
const viz::BeginFrameArgs& new_args) const;
void SetPartialUpdateDeciderWhenWaitingOnMain(
std::unique_ptr<CompositorFrameReporter>& reporter);
void TrackSwapTiming(const viz::FrameTimingDetails& details);
void ReportMultipleSwaps(base::TimeTicks begin_frame_time,
base::TimeDelta interval);
void AddSortedFrame(const viz::BeginFrameArgs& args,
const FrameInfo& frame_info);
const bool should_report_histograms_;
const int layer_tree_host_id_;
viz::BeginFrameId last_submitted_frame_id_;
bool next_activate_has_invalidation_ = false;
ActiveTrackers active_trackers_;
FrameInfo::SmoothEffectDrivingThread scrolling_thread_ =
FrameInfo::SmoothEffectDrivingThread::kUnknown;
bool is_compositor_thread_driving_smoothness_ = false;
bool is_main_thread_driving_smoothness_ = false;
std::map<base::TimeTicks, CompositorFrameReporter::SmoothThread>
smooth_thread_history_;
std::unique_ptr<LatencyUkmReporter> latency_ukm_reporter_;
std::unique_ptr<PredictorJankTracker> predictor_jank_tracker_;
std::unique_ptr<CompositorFrameReporter>
reporters_[PipelineStage::kNumPipelineStages];
base::circular_deque<SubmittedCompositorFrame> submitted_compositor_frames_;
struct {
viz::BeginFrameArgs args;
FrameInfo::SmoothEffectDrivingThread scrolling_thread =
FrameInfo::SmoothEffectDrivingThread::kUnknown;
ActiveTrackers active_trackers;
CompositorFrameReporter::SmoothThread smooth_thread =
CompositorFrameReporter::SmoothThread::kSmoothNone;
} last_started_compositor_frame_;
base::TimeTicks begin_main_frame_start_time_;
raw_ptr<const base::TickClock> tick_clock_ =
base::DefaultTickClock::GetInstance();
GlobalMetricsTrackers global_trackers_;
std::map<viz::BeginFrameId, EventMetrics::List>
events_metrics_from_dropped_frames_;
std::queue<base::TimeTicks> latest_swap_times_;
base::TimeDelta last_interval_;
CompositorFrameReporter::CompositorLatencyInfo
previous_latency_predictions_main_;
CompositorFrameReporter::CompositorLatencyInfo
previous_latency_predictions_impl_;
CompositorFrameReporter::EventLatencyInfo event_latency_predictions_;
bool visible_ = true;
bool waiting_for_did_present_after_visible_ = false;
};
}
#endif