Commit 33133e55 authored by Mitsuru Oshima's avatar Mitsuru Oshima Committed by Commit Bot

Observe current compositor's FPS

* Changed FPSGraphPageView to observe the PresentationFeedback
* Reset the data when refresh rate changes because the data before
  change is not relevant anymore.

Bug: None
Change-Id: I4e0d8ef860b99255e2c6ad10d8f845a1e18c0ac9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2517779Reviewed-by: default avatarAlexander Alekseev <alemate@chromium.org>
Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#824540}
parent 1a164fd7
...@@ -10,17 +10,10 @@ ...@@ -10,17 +10,10 @@
namespace ash { namespace ash {
namespace hud_display { namespace hud_display {
CompositorStats::CompositorStats(Observer* observer, ui::Compositor* compositor) CompositorStats::CompositorStats() = default;
: observer_(observer), compositor_(compositor) { CompositorStats::~CompositorStats() = default;
compositor_->AddObserver(this);
}
CompositorStats::~CompositorStats() {
compositor_->RemoveObserver(this);
}
void CompositorStats::OnDidPresentCompositorFrame( void CompositorStats::OnDidPresentCompositorFrame(
uint32_t frame_token,
const gfx::PresentationFeedback& feedback) { const gfx::PresentationFeedback& feedback) {
constexpr base::TimeDelta kOneSec = base::TimeDelta::FromSeconds(1); constexpr base::TimeDelta kOneSec = base::TimeDelta::FromSeconds(1);
constexpr base::TimeDelta k500ms = base::TimeDelta::FromMilliseconds(500); constexpr base::TimeDelta k500ms = base::TimeDelta::FromMilliseconds(500);
...@@ -31,18 +24,13 @@ void CompositorStats::OnDidPresentCompositorFrame( ...@@ -31,18 +24,13 @@ void CompositorStats::OnDidPresentCompositorFrame(
while (!presented_times_.empty() && presented_times_.front() <= deadline_1s) while (!presented_times_.empty() && presented_times_.front() <= deadline_1s)
presented_times_.pop_front(); presented_times_.pop_front();
const float frame_rate_1s = presented_times_.size();
const base::TimeTicks deadline_500ms = feedback.timestamp - k500ms; const base::TimeTicks deadline_500ms = feedback.timestamp - k500ms;
float frame_rate_500ms = 0; frame_rate_for_last_half_second_ = 0;
for (auto i = presented_times_.crbegin(); for (auto i = presented_times_.crbegin();
(i != presented_times_.crend()) && (*i > deadline_500ms); ++i) { (i != presented_times_.crend()) && (*i > deadline_500ms); ++i) {
++frame_rate_500ms; ++frame_rate_for_last_half_second_;
} }
frame_rate_for_last_half_second_ *= 2;
frame_rate_500ms *= 2; // per second
observer_->OnFramePresented(frame_rate_1s, frame_rate_500ms,
compositor_->refresh_rate());
} }
} // namespace hud_display } // namespace hud_display
......
...@@ -7,11 +7,7 @@ ...@@ -7,11 +7,7 @@
#include "base/containers/circular_deque.h" #include "base/containers/circular_deque.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "ui/compositor/compositor_observer.h"
namespace ui {
class Compositor;
}
namespace gfx { namespace gfx {
struct PresentationFeedback; struct PresentationFeedback;
} }
...@@ -19,29 +15,24 @@ struct PresentationFeedback; ...@@ -19,29 +15,24 @@ struct PresentationFeedback;
namespace ash { namespace ash {
namespace hud_display { namespace hud_display {
class CompositorStats : public ui::CompositorObserver { class CompositorStats {
public: public:
class Observer { CompositorStats();
public: CompositorStats(const CompositorStats&) = delete;
Observer() = default; CompositorStats& operator=(const CompositorStats&) = delete;
virtual ~Observer() = default; ~CompositorStats();
virtual void OnFramePresented(float frame_rate_1s, float frame_rate_for_last_second() const { return presented_times_.size(); }
float frame_rate_500ms,
float refresh_rate) = 0;
};
CompositorStats(Observer* observer, ui::Compositor* compositor); float frame_rate_for_last_half_second() const {
~CompositorStats() override; return frame_rate_for_last_half_second_;
}
// ui::CompositorObserver: // Updates the stats with |feedback|.
void OnDidPresentCompositorFrame( void OnDidPresentCompositorFrame(const gfx::PresentationFeedback& feedback);
uint32_t frame_token,
const gfx::PresentationFeedback& feedback) override;
private: private:
Observer* const observer_; float frame_rate_for_last_half_second_;
ui::Compositor* const compositor_;
// |timestamp| from PresentationFeedback for one second. // |timestamp| from PresentationFeedback for one second.
base::circular_deque<base::TimeTicks> presented_times_; base::circular_deque<base::TimeTicks> presented_times_;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "ui/aura/window_tree_host.h" #include "ui/aura/window_tree_host.h"
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/views/metadata/metadata_impl_macros.h" #include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/widget/widget.h"
namespace ash { namespace ash {
namespace hud_display { namespace hud_display {
...@@ -46,10 +47,7 @@ FPSGraphPageView::FPSGraphPageView(const base::TimeDelta refresh_interval) ...@@ -46,10 +47,7 @@ FPSGraphPageView::FPSGraphPageView(const base::TimeDelta refresh_interval)
Graph::Baseline::BASELINE_BOTTOM, Graph::Baseline::BASELINE_BOTTOM,
Graph::Fill::NONE, Graph::Fill::NONE,
Graph::Style::SKYLINE, Graph::Style::SKYLINE,
kHUDBackground /*not drawn*/), kHUDBackground /*not drawn*/) {
compositor_stats_(
this,
Shell::Get()->GetAllRootWindows().front()->GetHost()->compositor()) {
const int data_width = frame_rate_1s_.max_data_points(); const int data_width = frame_rate_1s_.max_data_points();
// Verical ticks are drawn every 5 frames (5/60 interval). // Verical ticks are drawn every 5 frames (5/60 interval).
constexpr float vertical_ticks_interval = kVerticalTicFrames / 60.0; constexpr float vertical_ticks_interval = kVerticalTicFrames / 60.0;
...@@ -84,9 +82,12 @@ FPSGraphPageView::FPSGraphPageView(const base::TimeDelta refresh_interval) ...@@ -84,9 +82,12 @@ FPSGraphPageView::FPSGraphPageView(const base::TimeDelta refresh_interval)
"second scaled to a second."), "second scaled to a second."),
formatter_float}}); formatter_float}});
CreateLegend(legend); CreateLegend(legend);
AddObserver(this);
} }
FPSGraphPageView::~FPSGraphPageView() = default; FPSGraphPageView::~FPSGraphPageView() {
RemoveObserver(this);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -107,11 +108,18 @@ void FPSGraphPageView::OnPaint(gfx::Canvas* canvas) { ...@@ -107,11 +108,18 @@ void FPSGraphPageView::OnPaint(gfx::Canvas* canvas) {
// grid calculations. // grid calculations.
} }
void FPSGraphPageView::OnFramePresented(float frame_rate_1s, void FPSGraphPageView::OnDidPresentCompositorFrame(
float frame_rate_500ms, uint32_t frame_token,
float refresh_rate) { const gfx::PresentationFeedback& feedback) {
compositor_stats_.OnDidPresentCompositorFrame(feedback);
float frame_rate_1s = compositor_stats_.frame_rate_for_last_second();
float frame_rate_500ms = compositor_stats_.frame_rate_for_last_half_second();
float refresh_rate = GetWidget()->GetCompositor()->refresh_rate();
UpdateTopLabel(refresh_rate); UpdateTopLabel(refresh_rate);
frame_rate_1s_.AddValue(frame_rate_1s / grid_->top_label(), frame_rate_1s); frame_rate_1s_.AddValue(frame_rate_1s / grid_->top_label(), frame_rate_1s);
frame_rate_500ms_.AddValue(frame_rate_500ms / grid_->top_label(), frame_rate_500ms_.AddValue(frame_rate_500ms / grid_->top_label(),
frame_rate_500ms); frame_rate_500ms);
...@@ -120,19 +128,44 @@ void FPSGraphPageView::OnFramePresented(float frame_rate_1s, ...@@ -120,19 +128,44 @@ void FPSGraphPageView::OnFramePresented(float frame_rate_1s,
refresh_rate_.AddValue(max_refresh_rate / grid_->top_label(), refresh_rate_.AddValue(max_refresh_rate / grid_->top_label(),
max_refresh_rate); max_refresh_rate);
// Legend update is expensive. Do it synchronously on regular intervals only. // Legend update is expensive. Do it synchronously on regular intervals only.
SchedulePaint(); if (GetVisible())
SchedulePaint();
} }
void FPSGraphPageView::UpdateData(const DataSource::Snapshot& snapshot) { void FPSGraphPageView::UpdateData(const DataSource::Snapshot& snapshot) {
if (!GetWidget()->GetNativeWindow()->HasObserver(this)) {
GetWidget()->GetNativeWindow()->AddObserver(this);
GetWidget()->GetCompositor()->AddObserver(this);
}
// Graph moves only on FramePresented. // Graph moves only on FramePresented.
// Update legend only. // Update legend only.
RefreshLegendValues(); RefreshLegendValues();
} }
void FPSGraphPageView::OnViewRemovedFromWidget(View* observed_view) {
// Remove observe for destruction.
GetWidget()->GetNativeWindow()->RemoveObserver(this);
GetWidget()->GetCompositor()->RemoveObserver(this);
}
void FPSGraphPageView::OnWindowAddedToRootWindow(aura::Window* window) {
GetWidget()->GetCompositor()->AddObserver(this);
}
void FPSGraphPageView::OnWindowRemovingFromRootWindow(aura::Window* window,
aura::Window* new_root) {
if (GetWidget() && GetWidget()->GetCompositor() &&
GetWidget()->GetCompositor()->HasObserver(this)) {
GetWidget()->GetCompositor()->RemoveObserver(this);
}
}
void FPSGraphPageView::UpdateTopLabel(float refresh_rate) { void FPSGraphPageView::UpdateTopLabel(float refresh_rate) {
if (grid_->top_label() < unsigned(refresh_rate)) { const float refresh_rate_rounded_10 =
const unsigned refresh_rate_rounded_10 = ceilf(unsigned(refresh_rate) / 10.0F) * 10;
ceilf(unsigned(refresh_rate) / 10.0F) * 10; if (grid_->top_label() != refresh_rate_rounded_10) {
frame_rate_1s_.Reset();
frame_rate_500ms_.Reset();
grid_->SetTopLabel(refresh_rate_rounded_10); grid_->SetTopLabel(refresh_rate_rounded_10);
grid_->SetVerticalTicsInterval(kVerticalTicFrames / grid_->SetVerticalTicsInterval(kVerticalTicFrames /
refresh_rate_rounded_10); refresh_rate_rounded_10);
......
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
#include "ash/hud_display/compositor_stats.h" #include "ash/hud_display/compositor_stats.h"
#include "ash/hud_display/graph.h" #include "ash/hud_display/graph.h"
#include "ash/hud_display/graph_page_view_base.h" #include "ash/hud_display/graph_page_view_base.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/views/view_observer.h"
namespace ash { namespace ash {
namespace hud_display { namespace hud_display {
...@@ -21,7 +24,9 @@ class Grid; ...@@ -21,7 +24,9 @@ class Grid;
// 1. Regular update with UpdateData() sifts graph and adds new point. // 1. Regular update with UpdateData() sifts graph and adds new point.
// 2. Every time OnFramePresented() is called, the last graph value is updated. // 2. Every time OnFramePresented() is called, the last graph value is updated.
class FPSGraphPageView : public GraphPageViewBase, class FPSGraphPageView : public GraphPageViewBase,
public CompositorStats::Observer { public ui::CompositorObserver,
public views::ViewObserver,
public aura::WindowObserver {
public: public:
METADATA_HEADER(FPSGraphPageView); METADATA_HEADER(FPSGraphPageView);
...@@ -30,16 +35,22 @@ class FPSGraphPageView : public GraphPageViewBase, ...@@ -30,16 +35,22 @@ class FPSGraphPageView : public GraphPageViewBase,
FPSGraphPageView& operator=(const FPSGraphPageView&) = delete; FPSGraphPageView& operator=(const FPSGraphPageView&) = delete;
~FPSGraphPageView() override; ~FPSGraphPageView() override;
// views::View // GraphPageViewBase:
void OnPaint(gfx::Canvas* canvas) override; void OnPaint(gfx::Canvas* canvas) override;
void UpdateData(const DataSource::Snapshot& snapshot) override;
// CompositorStats::Observer // ui::CompositorObserver:
void OnFramePresented(float frame_rate_1s, void OnDidPresentCompositorFrame(
float frame_rate_500ms, uint32_t frame_token,
float refresh_rate) override; const gfx::PresentationFeedback& feedback) override;
// Update page data from the new snapshot. // views::ViewObserver:
void UpdateData(const DataSource::Snapshot& snapshot) override; void OnViewRemovedFromWidget(views::View* observed_view) override;
// aura::WindowObserver:
void OnWindowAddedToRootWindow(aura::Window* window) override;
void OnWindowRemovingFromRootWindow(aura::Window* window,
aura::Window* new_root) override;
private: private:
// Sets grid top label to the maximum of the observed refresh rate. // Sets grid top label to the maximum of the observed refresh rate.
......
...@@ -209,6 +209,11 @@ bool Graph::IsFilledIndex(size_t index) const { ...@@ -209,6 +209,11 @@ bool Graph::IsFilledIndex(size_t index) const {
return data_.IsFilledIndex(raw_index); return data_.IsFilledIndex(raw_index);
} }
void Graph::Reset() {
data_.Clear();
unscaled_data_.Clear();
}
#if !defined(NDEBUG) #if !defined(NDEBUG)
std::string Graph::DebugDump(const std::string& name) const { std::string Graph::DebugDump(const std::string& name) const {
std::ostringstream os; std::ostringstream os;
......
...@@ -82,6 +82,9 @@ class Graph { ...@@ -82,6 +82,9 @@ class Graph {
// points from the right graph edge. // points from the right graph edge.
bool IsFilledIndex(size_t index) const; bool IsFilledIndex(size_t index) const;
// Reset the data.
void Reset();
#if !defined(NDEBUG) #if !defined(NDEBUG)
// Returns string representation os this object for debug. // Returns string representation os this object for debug.
std::string DebugDump(const std::string& name) const; std::string DebugDump(const std::string& name) const;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment