File indexing completed on 2024-11-10 04:57:23

0001 /*
0002     SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "utils/softwarevsyncmonitor.h"
0008 
0009 namespace KWin
0010 {
0011 
0012 std::unique_ptr<SoftwareVsyncMonitor> SoftwareVsyncMonitor::create()
0013 {
0014     return std::unique_ptr<SoftwareVsyncMonitor>{new SoftwareVsyncMonitor()};
0015 }
0016 
0017 SoftwareVsyncMonitor::SoftwareVsyncMonitor()
0018 {
0019     connect(&m_softwareClock, &QTimer::timeout, this, &SoftwareVsyncMonitor::handleSyntheticVsync);
0020     m_softwareClock.setSingleShot(true);
0021 }
0022 
0023 int SoftwareVsyncMonitor::refreshRate() const
0024 {
0025     return m_refreshRate;
0026 }
0027 
0028 void SoftwareVsyncMonitor::setRefreshRate(int refreshRate)
0029 {
0030     m_refreshRate = refreshRate;
0031 }
0032 
0033 void SoftwareVsyncMonitor::handleSyntheticVsync()
0034 {
0035     Q_EMIT vblankOccurred(m_vblankTimestamp);
0036 }
0037 
0038 template<typename T>
0039 T alignTimestamp(const T &timestamp, const T &alignment)
0040 {
0041     return timestamp + ((alignment - (timestamp % alignment)) % alignment);
0042 }
0043 
0044 void SoftwareVsyncMonitor::arm()
0045 {
0046     if (m_softwareClock.isActive()) {
0047         return;
0048     }
0049 
0050     const std::chrono::nanoseconds currentTime(std::chrono::steady_clock::now().time_since_epoch());
0051     const std::chrono::nanoseconds vblankInterval(1'000'000'000'000ull / m_refreshRate);
0052 
0053     m_vblankTimestamp = alignTimestamp(currentTime, vblankInterval);
0054 
0055     m_softwareClock.start(std::chrono::duration_cast<std::chrono::milliseconds>(m_vblankTimestamp - currentTime));
0056 }
0057 
0058 } // namespace KWin
0059 
0060 #include "moc_softwarevsyncmonitor.cpp"