diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -502,6 +502,7 @@ touch_hide_cursor_spy.cpp internal_client.cpp xwl/xwayland_interface.cpp + frame_statistics.cpp ) include(ECMQtDeclareLoggingCategory) diff --git a/composite.h b/composite.h --- a/composite.h +++ b/composite.h @@ -21,6 +21,7 @@ #pragma once #include +#include "frame_statistics.h" #include #include @@ -80,6 +81,10 @@ **/ void bufferSwapComplete(); + const FrameStatistics &frameStatistics() const { + return m_frameStatistics; + } + /** * @brief Suspends the Compositor if it is currently active. * @@ -221,6 +226,7 @@ int m_framesToTestForSafety = 3; QElapsedTimer m_monotonicClock; + FrameStatistics m_frameStatistics; KWIN_SINGLETON_VARIABLE(Compositor, s_compositor) }; diff --git a/composite.cpp b/composite.cpp --- a/composite.cpp +++ b/composite.cpp @@ -273,6 +273,7 @@ } connect(m_scene, &Scene::resetCompositing, this, &Compositor::reinitialize); + m_frameStatistics.reset(); emit sceneCreated(); if (Workspace::self()) { @@ -763,6 +764,7 @@ } else { scheduleRepaint(); } + m_frameStatistics.addFrame(); } template diff --git a/frame_statistics.h b/frame_statistics.h new file mode 100644 --- /dev/null +++ b/frame_statistics.h @@ -0,0 +1,59 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2019 Martin Flöser + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#pragma once +#include +#include + +namespace KWin +{ + +/** + * Simple class to record the render time of the last frames. + **/ +class FrameStatistics +{ +public: + /** + * Records the rendering of a frame. + **/ + void addFrame(); + /** + * Resets the statistics. E.g. to be used when restarting the compositor or after waking up + * from suspend. + **/ + void reset(); + + /** + * The number of frames currently recorded. + **/ + std::size_t numberOfFrames() const; + + /** + * The time in milliseconds between last recorded and first recorded frame. + **/ + std::chrono::milliseconds measuredTime() const; + +private: + std::size_t m_framesToKeep = 720u; + std::queue m_frameTimes; + +}; + +} diff --git a/frame_statistics.cpp b/frame_statistics.cpp new file mode 100644 --- /dev/null +++ b/frame_statistics.cpp @@ -0,0 +1,53 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2019 Martin Flöser + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "frame_statistics.h" + +namespace KWin +{ + +void FrameStatistics::addFrame() +{ + m_frameTimes.push(std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch())); + if (m_frameTimes.size() > m_framesToKeep) { + m_frameTimes.pop(); + } +} + +void FrameStatistics::reset() +{ + while (!m_frameTimes.empty()) { + m_frameTimes.pop(); + } +} + +std::size_t FrameStatistics::numberOfFrames() const +{ + return m_frameTimes.size(); +} + +std::chrono::milliseconds FrameStatistics::measuredTime() const +{ + if (m_frameTimes.empty()) { + return std::chrono::milliseconds::zero(); + } + return m_frameTimes.back() - m_frameTimes.front(); +} + +} diff --git a/workspace.cpp b/workspace.cpp --- a/workspace.cpp +++ b/workspace.cpp @@ -1607,6 +1607,14 @@ default: support.append(QStringLiteral("Something is really broken, neither OpenGL nor XRender is used")); } + + support.append(i18n("\nRendering statistics:\n")); + support.append(i18n("Please note: KWin renders on demand and does not keep a constant frame rate.\n" + "Due to that the recorded frame rate is expected to be significantly lower than the screen refresh rate.\n" + "In case of multiple screens with different refresh rates, the screen with the lowest refresh rate is the reference.\n")); + const auto &statistics = Compositor::self()->frameStatistics(); + support.append(i18n("%1 frames rendered during the last %2 msec.\n", statistics.numberOfFrames(), statistics.measuredTime().count())); + support.append(QStringLiteral("\nLoaded Effects:\n")); support.append(QStringLiteral( "---------------\n")); foreach (const QString &effect, static_cast(effects)->loadedEffects()) {