| // 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 <stdint.h> |
| |
| #include <memory> |
| |
| #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<Reporter> CreateHistogramReporter( |
| const char* latency_histogram_name, |
| absl::optional<const char*> max_latency_histogram_name = absl::nullopt); |
| |
| ShellSurfacePresentationTimeRecorder(ShellSurface* shell_surface, |
| std::unique_ptr<Reporter> 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<uint32_t> 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> reporter_; |
| |
| uint64_t next_request_id_ = 0u; |
| |
| // Request waiting for configure. There would be only one such request. |
| absl::optional<Request> pending_request_; |
| |
| // Requests that have received "configure" and wait for "ack". |
| base::circular_deque<Request> requests_; |
| |
| base::ScopedObservation<ShellSurface, ShellSurfaceObserver> |
| scoped_observation_{this}; |
| base::WeakPtrFactory<ShellSurfacePresentationTimeRecorder> weak_ptr_factory_{ |
| this}; |
| }; |
| |
| } // namespace exo |
| |
| #endif // COMPONENTS_EXO_SHELL_SURFACE_PRESENTATION_TIME_RECORDER_H_ |