// Copyright 2022 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_EXO_SHELL_SURFACE_PRESENTATION_TIME_RECORDER_H_ #define COMPONENTS_EXO_SHELL_SURFACE_PRESENTATION_TIME_RECORDER_H_ #include #include #include "ash/public/cpp/presentation_time_recorder.h" #include "base/containers/circular_deque.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" #include "base/time/time.h" #include "components/exo/shell_surface.h" #include "components/exo/shell_surface_observer.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace gfx { struct PresentationFeedback; } namespace exo { // ShellSurfacePresentationTimeRecorder records the time of // configure-> ack -> present // of the underlying ShellSurface after a request is made. Requests // made for the same configure will be ignored. class ShellSurfacePresentationTimeRecorder : public ash::PresentationTimeRecorder, public ShellSurfaceObserver { public: class Reporter { public: virtual ~Reporter() = default; // Invoked to report the time delta. virtual void ReportTime(base::TimeDelta delta) = 0; }; // Factory to create histogram reporter. static std::unique_ptr CreateHistogramReporter( const char* latency_histogram_name, absl::optional max_latency_histogram_name = absl::nullopt); ShellSurfacePresentationTimeRecorder(ShellSurface* shell_surface, std::unique_ptr reporter); ShellSurfacePresentationTimeRecorder( const ShellSurfacePresentationTimeRecorder&) = delete; ShellSurfacePresentationTimeRecorder& operator=( const ShellSurfacePresentationTimeRecorder&) = delete; ~ShellSurfacePresentationTimeRecorder() override; // ash::PresentationTimeRecorder: void PrepareToRecord() override; bool RequestNext() override; // ShellSurfaceObserver: void OnConfigure(uint32_t serial) override; void OnAcknowledgeConfigure(uint32_t serial) override; void OnShellSurfaceDestroyed() override; protected: struct Request { uint64_t request_id = 0u; // Time when RequestNext is called. base::TimeTicks request_time; // Serial of the first Configure after RequestNext. absl::optional serial = absl::nullopt; }; // Invoked to notify a frame is presented to calculate time delta between // `request_time` and the frame's presentation feedback. // Virtual for testing. virtual void OnFramePresented(const Request& request, const gfx::PresentationFeedback& feedback); private: ShellSurface* shell_surface_ = nullptr; std::unique_ptr reporter_; uint64_t next_request_id_ = 0u; // Request waiting for configure. There would be only one such request. absl::optional pending_request_; // Requests that have received "configure" and wait for "ack". base::circular_deque requests_; base::ScopedObservation scoped_observation_{this}; base::WeakPtrFactory weak_ptr_factory_{ this}; }; } // namespace exo #endif // COMPONENTS_EXO_SHELL_SURFACE_PRESENTATION_TIME_RECORDER_H_