blob: 83e85e7b8136ce0b1b8b59811b2b12074d894c43 [file] [log] [blame]
// Copyright 2024 The Fuchsia 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 "src/graphics/display/drivers/coordinator/vsync-monitor.h"
#include <lib/async-loop/loop.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/zx/clock.h>
#include <lib/zx/result.h>
#include <lib/zx/time.h>
#include <atomic>
#include "src/graphics/display/lib/api-types-cpp/config-stamp.h"
#include "src/graphics/display/lib/driver-framework-migration-utils/logging/zxlogf.h"
namespace display {
namespace {
// vsync delivery is considered to be stalled if at least this amount of time
// has elapsed since vsync was last observed.
constexpr zx::duration kVsyncStallThreshold = zx::sec(10);
constexpr zx::duration kVsyncMonitorInterval = kVsyncStallThreshold / 2;
} // namespace
VsyncMonitor::VsyncMonitor(inspect::Node inspect_root)
: inspect_root_(std::move(inspect_root)),
last_vsync_ns_property_(inspect_root_.CreateUint("last_vsync_timestamp_ns", 0)),
last_vsync_interval_ns_property_(inspect_root_.CreateUint("last_vsync_interval_ns", 0)),
last_vsync_config_stamp_property_(
inspect_root_.CreateUint("last_vsync_config_stamp", kInvalidConfigStamp.value())),
vsync_stalls_detected_(inspect_root_.CreateUint("vsync_stalls", 0)),
updater_loop_(&kAsyncLoopConfigNeverAttachToThread) {}
VsyncMonitor::~VsyncMonitor() { Deinitialize(); }
zx::result<> VsyncMonitor::Initialize() {
zx_status_t post_status = updater_.PostDelayed(updater_loop_.dispatcher(), kVsyncMonitorInterval);
if (post_status != ZX_OK) {
zxlogf(ERROR, "Failed to schedule vsync monitor: %s", zx_status_get_string(post_status));
return zx::error(post_status);
}
return zx::ok();
}
void VsyncMonitor::Deinitialize() { updater_.Cancel(); }
void VsyncMonitor::UpdateStatistics() {
if (vsync_stalled_) {
return;
}
zx::time now = zx::clock::get_monotonic();
zx::duration since_last_vsync = now - last_vsync_timestamp_.load();
if (since_last_vsync > kVsyncStallThreshold) {
vsync_stalled_ = true;
vsync_stalls_detected_.Add(1);
}
zx_status_t status = updater_.PostDelayed(updater_loop_.dispatcher(), kVsyncMonitorInterval);
if (status != ZX_OK) {
zxlogf(ERROR, "Failed to schedule vsync monitor: %s", zx_status_get_string(status));
}
}
void VsyncMonitor::OnVsync(zx::time vsync_timestamp, ConfigStamp vsync_config_stamp) {
last_vsync_ns_property_.Set(vsync_timestamp.get());
zx::duration vsync_interval =
vsync_timestamp - last_vsync_timestamp_.load(std::memory_order_relaxed);
last_vsync_interval_ns_property_.Set(vsync_interval.to_nsecs());
last_vsync_config_stamp_property_.Set(vsync_config_stamp.value());
last_vsync_timestamp_.store(vsync_timestamp);
vsync_stalled_ = false;
}
} // namespace display