blob: 2b8df3a3da7459d0dc4b538ae02522cbbb9ed717 [file] [log] [blame]
// Copyright 2019 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_SEQUENCE_TRACKER_H_
#define CC_METRICS_FRAME_SEQUENCE_TRACKER_H_
#include <memory>
#include <sstream>
#include "base/containers/circular_deque.h"
#include "base/containers/flat_set.h"
#include "base/time/time.h"
#include "cc/cc_export.h"
#include "cc/metrics/frame_sequence_metrics.h"
namespace gfx {
struct PresentationFeedback;
}
namespace viz {
struct BeginFrameArgs;
struct BeginFrameId;
} // namespace viz
namespace cc {
// Tracks a sequence of frames to determine the throughput. It tracks this by
// tracking the vsync sequence-numbers (from |BeginFrameArgs::sequence_number|),
// and the presentation-timestamps (from |gfx::PresentationFeedback|).
// This object should be created through
// FrameSequenceTrackerCollection::CreateTracker() API.
class CC_EXPORT FrameSequenceTracker {
public:
enum class TerminationStatus {
kActive,
kScheduledForTermination,
kReadyForTermination,
};
static const char* GetFrameSequenceTrackerTypeName(
FrameSequenceTrackerType type);
~FrameSequenceTracker();
FrameSequenceTracker(const FrameSequenceTracker&) = delete;
FrameSequenceTracker& operator=(const FrameSequenceTracker&) = delete;
// Notifies the tracker when the compositor thread starts to process a
// BeginFrameArgs.
void ReportBeginImplFrame(const viz::BeginFrameArgs& args);
// Notifies the tracker when the compositor thread has finished processing a
// BeginFrameArgs.
void ReportFrameEnd(const viz::BeginFrameArgs& args,
const viz::BeginFrameArgs& main_args);
// Notifies that frame production has currently paused. This is typically used
// for interactive frame-sequences, e.g. during touch-scroll.
void PauseFrameProduction();
TerminationStatus termination_status() const { return termination_status_; }
// Returns true if we should ask this tracker to report its throughput data.
bool ShouldReportMetricsNow(const viz::BeginFrameArgs& args) const;
FrameSequenceMetrics* metrics() { return metrics_.get(); }
FrameSequenceTrackerType type() const { return metrics_->type(); }
int custom_sequence_id() const { return custom_sequence_id_; }
std::unique_ptr<FrameSequenceMetrics> TakeMetrics();
// Called by the destructor of FrameSequenceTrackerCollection, asking its
// |metrics_| to report.
void CleanUp();
// Called by FrameSorter, this delivers `frame_info` merging both Compositor
// and Main thread updates for the given `args`. These are sorted by the
// `viz::BeginFrameArgs::frame_id` so we do not have to perform our own
// analysis of interleaving frames.
void AddSortedFrame(const viz::BeginFrameArgs& args,
const FrameInfo& frame_info);
private:
friend class FrameSequenceTrackerCollection;
friend class FrameSequenceTrackerTest;
// Constructs a tracker for a typed sequence other than kCustom.
explicit FrameSequenceTracker(FrameSequenceTrackerType type);
// Constructs a tracker for a kCustom typed sequence.
FrameSequenceTracker(int custom_sequence_id,
FrameSequenceMetrics::CustomReporter custom_reporter);
void ScheduleTerminate();
struct TrackedFrameData {
// Represents the |BeginFrameArgs::source_id| and
// |BeginFrameArgs::sequence_number| fields of the last processed
// BeginFrameArgs.
uint64_t previous_source = 0;
uint64_t previous_sequence = 0;
};
bool ShouldIgnoreBeginFrameSource(uint64_t source_id) const;
void ResetAllStateIfPaused();
const int custom_sequence_id_;
TerminationStatus termination_status_ = TerminationStatus::kActive;
TrackedFrameData begin_impl_frame_data_;
std::unique_ptr<FrameSequenceMetrics> metrics_;
// Keeps track of whether the frame-states should be reset.
bool reset_all_state_ = false;
// Report the throughput metrics every 5 seconds.
const base::TimeDelta time_delta_to_report_ = base::Seconds(5);
// True when an impl-impl is not ended. A tracker is ready for termination
// only when the last impl-frame is ended (ReportFrameEnd).
bool is_inside_frame_ = false;
// The args for the first frame that started after the tracker was created.
viz::BeginFrameArgs first_begin_frame_args_;
// Frame id of the last ended frame when the tracker is active.
viz::BeginFrameId last_ended_frame_id_;
// Frame id of the last sorted frame that the tracker was notified. If this is
// at least equal to `last_ended_frame_id_` then we are no longer awaiting
// frame feedback and can terminate immediately.
viz::BeginFrameId last_sorted_frame_id_;
};
} // namespace cc
#endif // CC_METRICS_FRAME_SEQUENCE_TRACKER_H_