diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index e6123f22857fda..84791f4fa7b424 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn @@ -226,6 +226,8 @@ component("cpp") { "personalization_app/user_display_info.h", "power_utils.cc", "power_utils.h", + "presentation_time_recorder.cc", + "presentation_time_recorder.h", "privacy_screen_dlp_helper.cc", "privacy_screen_dlp_helper.h", "projector/annotator_tool.cc", diff --git a/ash/public/cpp/presentation_time_recorder.cc b/ash/public/cpp/presentation_time_recorder.cc new file mode 100644 index 00000000000000..f58ce3f71fb7df --- /dev/null +++ b/ash/public/cpp/presentation_time_recorder.cc @@ -0,0 +1,58 @@ +// 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. + +#include "ash/public/cpp/presentation_time_recorder.h" + +#include + +#include "ui/aura/window.h" +#include "ui/compositor/layer.h" +#include "ui/compositor/presentation_time_recorder.h" + +namespace ash { + +namespace { + +// Wrapper class of ui::PresentationTimeRecorder that reports latency based +// on ui::Compositor. +class CompositorPresentationTimeRecorder : public PresentationTimeRecorder { + public: + CompositorPresentationTimeRecorder(aura::Window* window, + const char* latency_histogram_name, + const char* max_latency_histogram_name) + : compositor_recorder_(ui::CreatePresentationTimeHistogramRecorder( + window->layer()->GetCompositor(), + latency_histogram_name, + max_latency_histogram_name)) {} + + CompositorPresentationTimeRecorder( + const CompositorPresentationTimeRecorder&) = delete; + CompositorPresentationTimeRecorder& operator=( + const CompositorPresentationTimeRecorder&) = delete; + + ~CompositorPresentationTimeRecorder() override = default; + + // PresentationTimeRecorder: + bool RequestNext() override { return compositor_recorder_->RequestNext(); } + + private: + std::unique_ptr compositor_recorder_; +}; + +} // namespace + +// static +std::unique_ptr +PresentationTimeRecorder::CreateCompositorRecorder( + aura::Window* window, + const char* latency_histogram_name, + absl::optional max_latency_histogram_name) { + return std::make_unique( + window, latency_histogram_name, + max_latency_histogram_name.has_value() + ? max_latency_histogram_name.value() + : ""); +} + +} // namespace ash diff --git a/ash/public/cpp/presentation_time_recorder.h b/ash/public/cpp/presentation_time_recorder.h new file mode 100644 index 00000000000000..877ecd04d75540 --- /dev/null +++ b/ash/public/cpp/presentation_time_recorder.h @@ -0,0 +1,37 @@ +// 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 ASH_PUBLIC_CPP_PRESENTATION_TIME_RECORDER_H_ +#define ASH_PUBLIC_CPP_PRESENTATION_TIME_RECORDER_H_ + +#include + +#include "ash/public/cpp/ash_public_export.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace aura { +class Window; +} + +namespace ash { + +// A general interface for presentation time recording. +class ASH_PUBLIC_EXPORT PresentationTimeRecorder { + public: + // Creates a recorder tracking ui::Compositor. + static std::unique_ptr CreateCompositorRecorder( + aura::Window* window, + const char* latency_histogram_name, + absl::optional max_latency_histogram_name = absl::nullopt); + + virtual ~PresentationTimeRecorder() = default; + + // Request to record timing for the next frame. Returns true if the request + // is accepted. Otherwise, returns false. + virtual bool RequestNext() = 0; +}; + +} // namespace ash + +#endif // ASH_PUBLIC_CPP_PRESENTATION_TIME_RECORDER_H_ diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index 3e0a4d0d645a6f..3f3206cc42bf1c 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc @@ -6670,7 +6670,11 @@ class TestWindowStateDelegate : public WindowStateDelegate { ~TestWindowStateDelegate() override = default; // WindowStateDelegate: - void OnDragStarted(int component) override { drag_in_progress_ = true; } + std::unique_ptr OnDragStarted( + int component) override { + drag_in_progress_ = true; + return nullptr; + } void OnDragFinished(bool cancel, const gfx::PointF& location) override { drag_in_progress_ = false; } diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc index 01ddcf696b865c..b60f3d340466c7 100644 --- a/ash/wm/splitview/split_view_controller_unittest.cc +++ b/ash/wm/splitview/split_view_controller_unittest.cc @@ -359,7 +359,11 @@ class TestWindowStateDelegate : public WindowStateDelegate { ~TestWindowStateDelegate() override = default; // WindowStateDelegate: - void OnDragStarted(int component) override { drag_in_progress_ = true; } + std::unique_ptr OnDragStarted( + int component) override { + drag_in_progress_ = true; + return nullptr; + } void OnDragFinished(bool cancel, const gfx::PointF& location) override { drag_in_progress_ = false; } diff --git a/ash/wm/window_resizer.cc b/ash/wm/window_resizer.cc index 8ea3bb01cc9e06..ad6bef40a899f3 100644 --- a/ash/wm/window_resizer.cc +++ b/ash/wm/window_resizer.cc @@ -84,9 +84,8 @@ const int WindowResizer::kBoundsChangeDirection_Vertical = 2; WindowResizer::WindowResizer(WindowState* window_state) : window_state_(window_state) { - recorder_ = CreatePresentationTimeHistogramRecorder( - GetTarget()->layer()->GetCompositor(), - "Ash.InteractiveWindowResize.TimeToPresent", + recorder_ = PresentationTimeRecorder::CreateCompositorRecorder( + GetTarget(), "Ash.InteractiveWindowResize.TimeToPresent", "Ash.InteractiveWindowResize.TimeToPresent.MaxLatency"); DCHECK(window_state_->drag_details()); } diff --git a/ash/wm/window_resizer.h b/ash/wm/window_resizer.h index e9dce988d27ca6..a39a2a87c2a32d 100644 --- a/ash/wm/window_resizer.h +++ b/ash/wm/window_resizer.h @@ -11,7 +11,6 @@ #include "ash/wm/drag_details.h" #include "ash/wm/window_state.h" #include "base/memory/weak_ptr.h" -#include "ui/compositor/presentation_time_recorder.h" #include "ui/wm/public/window_move_client.h" namespace aura { @@ -27,6 +26,7 @@ class GestureEvent; } namespace ash { +class PresentationTimeRecorder; // WindowResizer is used by ToplevelWindowEventFilter to handle dragging, moving // or resizing a window. All coordinates passed to this are in the parent @@ -118,7 +118,7 @@ class ASH_EXPORT WindowResizer { void CalculateBoundsWithAspectRatio(float aspect_ratio, gfx::Rect* new_bounds); - std::unique_ptr recorder_; + std::unique_ptr recorder_; base::WeakPtrFactory weak_ptr_factory_{this}; }; diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc index a72464ec2bc84b..cd1503f305fe60 100644 --- a/ash/wm/window_state.cc +++ b/ash/wm/window_state.cc @@ -621,10 +621,13 @@ void WindowState::set_bounds_changed_by_user(bool bounds_changed_by_user) { } } -void WindowState::OnDragStarted(int window_component) { +std::unique_ptr WindowState::OnDragStarted( + int window_component) { DCHECK(drag_details_); if (delegate_) - delegate_->OnDragStarted(window_component); + return delegate_->OnDragStarted(window_component); + + return nullptr; } void WindowState::OnCompleteDrag(const gfx::PointF& location) { diff --git a/ash/wm/window_state.h b/ash/wm/window_state.h index e04bcc3768666c..671b75b7902531 100644 --- a/ash/wm/window_state.h +++ b/ash/wm/window_state.h @@ -10,6 +10,7 @@ #include "ash/ash_export.h" #include "ash/display/persistent_window_info.h" +#include "ash/public/cpp/presentation_time_recorder.h" #include "ash/wm/drag_details.h" #include "ash/wm/wm_metrics.h" #include "base/gtest_prod_util.h" @@ -350,8 +351,9 @@ class ASH_EXPORT WindowState : public aura::WindowObserver { // Sets the currently stored restore bounds and clears the restore bounds. void SetAndClearRestoreBounds(); - // Notifies that the drag operation has been started. - void OnDragStarted(int window_component); + // Notifies that the drag operation has been started. Optionally returns + // a presentation time recorder for the drag. + std::unique_ptr OnDragStarted(int window_component); // Notifies that the drag operation has been either completed or reverted. // |location| is the last position of the pointer device used to drag. diff --git a/ash/wm/window_state_delegate.cc b/ash/wm/window_state_delegate.cc index 12fbf0401de44d..6b2214aae14d9a 100644 --- a/ash/wm/window_state_delegate.cc +++ b/ash/wm/window_state_delegate.cc @@ -16,4 +16,9 @@ bool WindowStateDelegate::ToggleFullscreen(WindowState* window_state) { void WindowStateDelegate::ToggleLockedFullscreen(WindowState* window_state) {} +std::unique_ptr WindowStateDelegate::OnDragStarted( + int component) { + return nullptr; +} + } // namespace ash diff --git a/ash/wm/window_state_delegate.h b/ash/wm/window_state_delegate.h index 89cb7cf38f5fd1..23fe49bceefd69 100644 --- a/ash/wm/window_state_delegate.h +++ b/ash/wm/window_state_delegate.h @@ -5,7 +5,10 @@ #ifndef ASH_WM_WINDOW_STATE_DELEGATE_H_ #define ASH_WM_WINDOW_STATE_DELEGATE_H_ +#include + #include "ash/ash_export.h" +#include "ash/public/cpp/presentation_time_recorder.h" namespace gfx { class PointF; @@ -40,8 +43,10 @@ class ASH_EXPORT WindowStateDelegate { // Invoked when the user started drag operation. |component| must be // a member of ui::HitTestCompat enum and specifies which part of // the window the pointer device was on when the user started drag - // operation. - virtual void OnDragStarted(int component) {} + // operation. Returns a presentation time recorder that could be used to + // track resize latency. + virtual std::unique_ptr OnDragStarted( + int component); // Invoked when the user finished drag operation. |cancel| is true // if the drag operation was canceled. diff --git a/ash/wm/workspace/multi_window_resize_controller_unittest.cc b/ash/wm/workspace/multi_window_resize_controller_unittest.cc index 33f235c3011f94..3e54bcd31f9cb6 100644 --- a/ash/wm/workspace/multi_window_resize_controller_unittest.cc +++ b/ash/wm/workspace/multi_window_resize_controller_unittest.cc @@ -578,7 +578,11 @@ class TestWindowStateDelegate : public WindowStateDelegate { ~TestWindowStateDelegate() override = default; // WindowStateDelegate: - void OnDragStarted(int component) override { component_ = component; } + std::unique_ptr OnDragStarted( + int component) override { + component_ = component; + return nullptr; + } void OnDragFinished(bool cancel, const gfx::PointF& location) override { location_ = location; } diff --git a/ash/wm/workspace/workspace_window_resizer.h b/ash/wm/workspace/workspace_window_resizer.h index e19a35a99e24f6..a2f185cffaeb3d 100644 --- a/ash/wm/workspace/workspace_window_resizer.h +++ b/ash/wm/workspace/workspace_window_resizer.h @@ -13,7 +13,9 @@ #include "ash/wm/window_resizer.h" #include "ash/wm/workspace/magnetism_matcher.h" #include "base/memory/weak_ptr.h" +#include "base/timer/timer.h" #include "ui/aura/window_tracker.h" +#include "ui/compositor/presentation_time_recorder.h" #include "ui/display/display.h" #include "ui/gfx/geometry/point_f.h" diff --git a/components/exo/client_controlled_shell_surface.cc b/components/exo/client_controlled_shell_surface.cc index 501bcbb6bf39a3..b0777dd008c9bc 100644 --- a/components/exo/client_controlled_shell_surface.cc +++ b/components/exo/client_controlled_shell_surface.cc @@ -219,8 +219,10 @@ class ClientControlledWindowStateDelegate : public ash::WindowStateDelegate { return; } - void OnDragStarted(int component) override { + std::unique_ptr OnDragStarted( + int component) override { shell_surface_->OnDragStarted(component); + return nullptr; } void OnDragFinished(bool canceled, const gfx::PointF& location) override {