| // Copyright 2020 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_COLLECTION_H_ |
| #define CC_METRICS_FRAME_SEQUENCE_TRACKER_COLLECTION_H_ |
| |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/callback.h" |
| #include "base/containers/flat_map.h" |
| #include "base/memory/raw_ptr.h" |
| #include "cc/cc_export.h" |
| #include "cc/metrics/frame_sequence_metrics.h" |
| |
| namespace gfx { |
| struct PresentationFeedback; |
| } |
| |
| namespace viz { |
| struct BeginFrameAck; |
| struct BeginFrameArgs; |
| } // namespace viz |
| |
| namespace cc { |
| class FrameSequenceTracker; |
| class CompositorFrameReportingController; |
| class ThroughputUkmReporter; |
| class UkmManager; |
| |
| // Map of kCustom tracker results keyed by a sequence id. |
| using CustomTrackerResults = |
| base::flat_map<int, FrameSequenceMetrics::CustomReportData>; |
| |
| typedef uint16_t ActiveFrameSequenceTrackers; |
| |
| // Used for notifying attached FrameSequenceTracker's of begin-frames and |
| // submitted frames. |
| class CC_EXPORT FrameSequenceTrackerCollection { |
| public: |
| FrameSequenceTrackerCollection( |
| bool is_single_threaded, |
| CompositorFrameReportingController* frame_reporting_controller); |
| ~FrameSequenceTrackerCollection(); |
| |
| FrameSequenceTrackerCollection(const FrameSequenceTrackerCollection&) = |
| delete; |
| FrameSequenceTrackerCollection& operator=( |
| const FrameSequenceTrackerCollection&) = delete; |
| |
| // Creates a new tracker for the specified sequence-type if one doesn't |
| // already exist. Returns the associated FrameSequenceTracker instance. |
| FrameSequenceTracker* StartSequence(FrameSequenceTrackerType type); |
| FrameSequenceTracker* StartScrollSequence( |
| FrameSequenceTrackerType type, |
| FrameInfo::SmoothEffectDrivingThread scrolling_thread); |
| |
| // Schedules |tracker| for destruction. This is preferred instead of outright |
| // desrtruction of the tracker, since this ensures that the actual tracker |
| // instance is destroyed *after* the presentation-feedbacks have been received |
| // for all submitted frames. |
| void StopSequence(FrameSequenceTrackerType type); |
| |
| // Creates a kCustom tracker for the given sequence id. It is an error and |
| // DCHECKs if there is already a tracker associated with the sequence id. |
| void StartCustomSequence(int sequence_id); |
| |
| // Schedules the kCustom tracker representing |sequence_id| for destruction. |
| // It is a no-op if there is no tracker associated with the sequence id. |
| // Similar to StopSequence above, the tracker instance is destroyed *after* |
| // the presentation feedbacks have been received for all submitted frames. |
| void StopCustomSequence(int sequence_id); |
| |
| // Removes all trackers. This also immediately destroys all trackers that had |
| // been scheduled for destruction, even if there are pending |
| // presentation-feedbacks. This is typically used if the client no longer |
| // expects to receive presentation-feedbacks for the previously submitted |
| // frames (e.g. when the gpu process dies). |
| void ClearAll(); |
| |
| // Notifies all trackers of various events. |
| void NotifyBeginImplFrame(const viz::BeginFrameArgs& args); |
| void NotifyBeginMainFrame(const viz::BeginFrameArgs& args); |
| void NotifyMainFrameProcessed(const viz::BeginFrameArgs& args); |
| void NotifyImplFrameCausedNoDamage(const viz::BeginFrameAck& ack); |
| void NotifyMainFrameCausedNoDamage(const viz::BeginFrameArgs& args, |
| bool aborted); |
| void NotifyPauseFrameProduction(); |
| void NotifySubmitFrame(uint32_t frame_token, |
| bool has_missing_content, |
| const viz::BeginFrameAck& ack, |
| const viz::BeginFrameArgs& origin_args); |
| void NotifyFrameEnd(const viz::BeginFrameArgs& args, |
| const viz::BeginFrameArgs& main_args); |
| |
| // Note that this notifies the trackers of the presentation-feedbacks, and |
| // destroys any tracker that had been scheduled for destruction (using |
| // |ScheduleRemoval()|) if it has no more pending frames. Data from non |
| // kCustom typed trackers are reported to UMA. Data from kCustom typed |
| // trackers are added to |custom_tracker_results_| for caller to pick up. |
| void NotifyFramePresented(uint32_t frame_token, |
| const gfx::PresentationFeedback& feedback); |
| |
| // Return the type of each active frame tracker, encoded into a 16 bit |
| // integer with the bit at each position corresponding to the enum value of |
| // each type. |
| ActiveFrameSequenceTrackers FrameSequenceTrackerActiveTypes() const; |
| |
| FrameSequenceTracker* GetRemovalTrackerForTesting( |
| FrameSequenceTrackerType type); |
| |
| void SetUkmManager(UkmManager* manager); |
| |
| using NotifyCustomerTrackerResutlsCallback = |
| base::RepeatingCallback<void(const CustomTrackerResults&)>; |
| void set_custom_tracker_results_added_callback( |
| NotifyCustomerTrackerResutlsCallback callback) { |
| custom_tracker_results_added_callback_ = std::move(callback); |
| } |
| |
| void AddSortedFrame(const viz::BeginFrameArgs& args, |
| const FrameInfo& frame_info); |
| |
| private: |
| friend class FrameSequenceTrackerTest; |
| |
| FrameSequenceTracker* StartSequenceInternal( |
| FrameSequenceTrackerType type, |
| FrameInfo::SmoothEffectDrivingThread scrolling_thread); |
| |
| void RecreateTrackers(const viz::BeginFrameArgs& args); |
| // Destroy the trackers that are ready to be terminated. |
| void DestroyTrackers(); |
| |
| // Ask all trackers to report their metrics if there is any, must be the first |
| // thing in the destructor. |
| void CleanUp(); |
| |
| // Adds collected metrics data for |custom_sequence_id| to be picked up via |
| // TakeCustomTrackerResults() below. |
| void AddCustomTrackerResult( |
| int custom_sequence_id, |
| const FrameSequenceMetrics::CustomReportData& data); |
| |
| const bool is_single_threaded_; |
| // The reporter takes throughput data and connect to UkmManager to report it. |
| // Note: this has to be before the frame_trackers_. The reason is that a |
| // FrameSequenceTracker owners a FrameSequenceMetrics, so the destructor of |
| // the former calls the destructor of the later. FrameSequenceMetrics's |
| // destructor calls its ReportMetrics() which requires |
| // |throughput_ukm_reporter_| to be alive. So putting it before |
| // |frame_trackers_| to ensure that it is destroyed after the tracker. |
| std::unique_ptr<ThroughputUkmReporter> throughput_ukm_reporter_; |
| |
| // The callsite can use the type to manipulate the tracker. |
| base::flat_map< |
| std::pair<FrameSequenceTrackerType, FrameInfo::SmoothEffectDrivingThread>, |
| std::unique_ptr<FrameSequenceTracker>> |
| frame_trackers_; |
| |
| // Custom trackers are keyed by a custom sequence id. |
| base::flat_map<int, std::unique_ptr<FrameSequenceTracker>> |
| custom_frame_trackers_; |
| |
| // Called when throughput metrics are available for custom trackers added by |
| // |AddCustomTrackerResult()|. |
| NotifyCustomerTrackerResutlsCallback custom_tracker_results_added_callback_; |
| |
| std::vector<std::unique_ptr<FrameSequenceTracker>> removal_trackers_; |
| const raw_ptr<CompositorFrameReportingController> |
| compositor_frame_reporting_controller_; |
| |
| base::flat_map< |
| std::pair<FrameSequenceTrackerType, FrameInfo::SmoothEffectDrivingThread>, |
| std::unique_ptr<FrameSequenceMetrics>> |
| accumulated_metrics_; |
| |
| // Tracks how many smoothness effects are driven by each thread. |
| size_t main_thread_driving_smoothness_ = 0; |
| size_t compositor_thread_driving_smoothness_ = 0; |
| }; |
| |
| } // namespace cc |
| |
| #endif // CC_METRICS_FRAME_SEQUENCE_TRACKER_COLLECTION_H_ |