From 5aa7a48f9382c2922497f45de5a9a0bbaa31048a Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Tue, 16 Aug 2022 14:54:02 +0200 Subject: [PATCH] Replace "Show FPS" effect with a QML version This removes a bunch of custom rendering, replacing it with a simple QML file that makes use of KQuickCharts for chart rendering. Functionally, it should be mostly the same except that I removed all configuration options as I don't see why we have those. --- src/effects/showfps/CMakeLists.txt | 34 +- src/effects/showfps/main.cpp | 7 +- src/effects/showfps/metadata.json | 3 +- src/effects/showfps/qml/main.qml | 195 +++++++++++ src/effects/showfps/showfps.cpp | 447 ------------------------ src/effects/showfps/showfps.h | 134 ------- src/effects/showfps/showfps.kcfg | 37 -- src/effects/showfps/showfps_config.cpp | 45 --- src/effects/showfps/showfps_config.h | 35 -- src/effects/showfps/showfps_config.ui | 230 ------------ src/effects/showfps/showfpsconfig.kcfgc | 5 - src/effects/showfps/showfpseffect.cpp | 126 +++++++ src/effects/showfps/showfpseffect.h | 65 ++++ 13 files changed, 399 insertions(+), 964 deletions(-) create mode 100644 src/effects/showfps/qml/main.qml delete mode 100644 src/effects/showfps/showfps.cpp delete mode 100644 src/effects/showfps/showfps.h delete mode 100644 src/effects/showfps/showfps.kcfg delete mode 100644 src/effects/showfps/showfps_config.cpp delete mode 100644 src/effects/showfps/showfps_config.h delete mode 100644 src/effects/showfps/showfps_config.ui delete mode 100644 src/effects/showfps/showfpsconfig.kcfgc create mode 100644 src/effects/showfps/showfpseffect.cpp create mode 100644 src/effects/showfps/showfpseffect.h diff --git a/src/effects/showfps/CMakeLists.txt b/src/effects/showfps/CMakeLists.txt index 7507de6bbe..6557029b23 100644 --- a/src/effects/showfps/CMakeLists.txt +++ b/src/effects/showfps/CMakeLists.txt @@ -1,38 +1,20 @@ -####################################### -# Effect +# SPDX-FileCopyrightText: 2022 Arjen Hiemstra +# +# SPDX-License-Identifier: BSD-3-Clause set(showfps_SOURCES main.cpp - showfps.cpp -) - -kconfig_add_kcfg_files(showfps_SOURCES - showfpsconfig.kcfgc + showfpseffect.cpp ) kwin4_add_effect_module(kwin4_effect_showfps ${showfps_SOURCES}) + target_link_libraries(kwin4_effect_showfps PRIVATE kwineffects - kwinglutils - KF5::ConfigGui KF5::I18n -) -####################################### -# Config -if (KWIN_BUILD_KCMS) - set(kwin_showfps_config_SRCS showfps_config.cpp) - ki18n_wrap_ui(kwin_showfps_config_SRCS showfps_config.ui) - kconfig_add_kcfg_files(kwin_showfps_config_SRCS showfpsconfig.kcfgc) - - kwin_add_effect_config(kwin_showfps_config ${kwin_showfps_config_SRCS}) - - target_link_libraries(kwin_showfps_config - KF5::ConfigWidgets - KF5::CoreAddons - KF5::I18n - Qt::DBus - KWinEffectsInterface + Qt::Quick ) -endif() + +install(DIRECTORY qml DESTINATION ${KDE_INSTALL_DATADIR}/kwin/effects/showfps) diff --git a/src/effects/showfps/main.cpp b/src/effects/showfps/main.cpp index 30169f9bfd..83711a955d 100644 --- a/src/effects/showfps/main.cpp +++ b/src/effects/showfps/main.cpp @@ -4,13 +4,14 @@ SPDX-License-Identifier: GPL-2.0-or-later */ -#include "showfps.h" +#include "showfpseffect.h" namespace KWin { -KWIN_EFFECT_FACTORY(ShowFpsEffect, - "metadata.json.stripped") +KWIN_EFFECT_FACTORY_SUPPORTED(ShowFpsEffect, + "metadata.json.stripped", + return ShowFpsEffect::supported();) } // namespace KWin diff --git a/src/effects/showfps/metadata.json b/src/effects/showfps/metadata.json index 60b3553ee1..b4454e194d 100644 --- a/src/effects/showfps/metadata.json +++ b/src/effects/showfps/metadata.json @@ -72,6 +72,5 @@ "Name[x-test]": "xxShow FPSxx", "Name[zh_CN]": "显示每秒帧数", "Name[zh_TW]": "顯示 FPS" - }, - "X-KDE-ConfigModule": "kwin_showfps_config" + } } diff --git a/src/effects/showfps/qml/main.qml b/src/effects/showfps/qml/main.qml new file mode 100644 index 0000000000..c17bb01677 --- /dev/null +++ b/src/effects/showfps/qml/main.qml @@ -0,0 +1,195 @@ +/* + SPDX-FileCopyrightText: 2022 Arjen Hiemstra + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import org.kde.kirigami 2.18 as Kirigami +import org.kde.quickcharts 1.0 as Charts +import org.kde.quickcharts.controls 1.0 as ChartControls + +Rectangle { + id: root + + required property QtObject effect + + readonly property color gridColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, + Kirigami.Theme.backgroundColor.g, + Kirigami.Theme.backgroundColor.b, + 0.25) + + color: Qt.rgba(1.0, 1.0, 1.0, 0.5) + + ColumnLayout { + anchors.fill: parent + + RowLayout { + Layout.fillWidth: true + Layout.fillHeight: true + + Charts.BarChart { + id: fpsChart + + Layout.preferredWidth: Kirigami.Units.gridUnit + Layout.fillHeight: true + + yRange.minimum: root.effect.maximumFps + 10 + yRange.increment: 10 + + valueSources: Charts.SingleValueSource { value: root.effect.fps } + + colorSource: Charts.SingleValueSource { value: Kirigami.Theme.highlightColor } + + Charts.GridLines { + anchors.fill: parent + z: -1 + + chart: fpsChart + + direction: Charts.GridLines.Vertical; + + major.visible: false + + minor.frequency: 10 + minor.lineWidth: 1 + minor.color: root.gridColor + } + } + + Charts.BarChart { + Layout.fillWidth: true + Layout.fillHeight: true + + yRange.minimum: 100 + yRange.increment: 10 + + xRange.from: 0 + xRange.to: 50 + xRange.automatic: false + + indexingMode: Charts.Chart.IndexSourceValues + + valueSources: Charts.HistoryProxySource { + source: Charts.SingleValueSource { + value: root.effect.paintDuration + } + maximumHistory: 100 + fillMode: Charts.HistoryProxySource.FillFromStart + } + + colorSource: Charts.HistoryProxySource { + source: Charts.SingleValueSource { + value: root.effect.paintColor + } + maximumHistory: 100 + fillMode: Charts.HistoryProxySource.FillFromStart + } + + Charts.GridLines { + anchors.fill: parent + z: -1 + + chart: parent + + direction: Charts.GridLines.Vertical; + + major.visible: false + + minor.frequency: 10 + minor.lineWidth: 1 + minor.color: root.gridColor + } + + Label { + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + text: i18nc("@label", "Paint Duration") + font: Kirigami.Theme.smallFont + } + } + + Charts.BarChart { + Layout.fillWidth: true + Layout.fillHeight: true + + yRange.minimum: Qt.application.screens[0].width * Qt.application.screens[0].height + yRange.increment: 500000 + + xRange.from: 0 + xRange.to: 50 + xRange.automatic: false + + indexingMode: Charts.Chart.IndexSourceValues + + valueSources: Charts.HistoryProxySource { + source: Charts.SingleValueSource { + value: root.effect.paintAmount + } + maximumHistory: 100 + fillMode: Charts.HistoryProxySource.FillFromStart + } + + colorSource: Charts.HistoryProxySource { + source: Charts.SingleValueSource { + value: root.effect.paintColor + } + maximumHistory: 100 + fillMode: Charts.HistoryProxySource.FillFromStart + } + + Charts.GridLines { + anchors.fill: parent + z: -1 + + chart: parent + + direction: Charts.GridLines.Vertical; + + major.visible: false + + minor.frequency: 100000 + minor.lineWidth: 1 + minor.color: root.gridColor + } + + Label { + anchors.top: parent.top + anchors.horizontalCenter: parent.horizontalCenter + text: i18nc("@label", "Paint Amount") + font: Kirigami.Theme.smallFont + } + } + } + + RowLayout { + Layout.fillWidth: true + + ChartControls.LegendDelegate { + Layout.fillWidth: true + Layout.preferredWidth: 0 + + name: i18nc("@label", "Current FPS") + value: root.effect.fps + color: Kirigami.Theme.highlightColor + } + + ChartControls.LegendDelegate { + Layout.fillWidth: true + Layout.preferredWidth: 0 + + name: i18nc("@label", "Maximum FPS") + value: root.effect.maximumFps + color: Kirigami.Theme.neutralTextColor + } + } + + Label { + Layout.fillWidth: true + text: i18nc("@label", "This effect is not a benchmark") + } + } +} diff --git a/src/effects/showfps/showfps.cpp b/src/effects/showfps/showfps.cpp deleted file mode 100644 index 5d18e44378..0000000000 --- a/src/effects/showfps/showfps.cpp +++ /dev/null @@ -1,447 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2006 Lubos Lunak - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -#include "showfps.h" - -// KConfigSkeleton -#include "showfpsconfig.h" - -#include - -#include - -#include - -#include -#include -#include - -#include - -namespace KWin -{ - -const int FPS_WIDTH = 10; -const int MAX_TIME = 100; - -ShowFpsEffect::ShowFpsEffect() - : paints_pos(0) - , frames_pos(0) - , m_noBenchmark(effects->effectFrame(EffectFrameUnstyled, false)) -{ - initConfig(); - for (int i = 0; i < NUM_PAINTS; i++) { - paints[i] = 0; - paint_size[i] = 0; - } - for (int i = 0; i < MAX_FPS; i++) { - frames[i] = 0; - } - if (m_showNoBenchmark) { - m_noBenchmark->setAlignment(Qt::AlignTop | Qt::AlignRight); - m_noBenchmark->setText(i18n("This effect is not a benchmark")); - } - reconfigure(ReconfigureAll); -} - -ShowFpsEffect::~ShowFpsEffect() = default; - -void ShowFpsEffect::reconfigure(ReconfigureFlags) -{ - ShowFpsConfig::self()->read(); - alpha = ShowFpsConfig::alpha(); - x = ShowFpsConfig::x(); - y = ShowFpsConfig::y(); - m_showNoBenchmark = ShowFpsConfig::showNoBenchmark(); - m_showGraph = ShowFpsConfig::showGraph(); - m_colorizeText = ShowFpsConfig::colorizeText(); - const QSize screenSize = effects->virtualScreenSize(); - if (x == -10000) { // there's no -0 :( - x = screenSize.width() - 2 * NUM_PAINTS - FPS_WIDTH; - } else if (x < 0) { - x = screenSize.width() - 2 * NUM_PAINTS - FPS_WIDTH - x; - } - if (y == -10000) { - y = screenSize.height() - MAX_TIME; - } else if (y < 0) { - y = screenSize.height() - MAX_TIME - y; - } - fps_rect = QRect(x, y, FPS_WIDTH + 2 * NUM_PAINTS, MAX_TIME); - m_noBenchmark->setPosition(fps_rect.bottomRight() + QPoint(-6, 6)); - - int textPosition = ShowFpsConfig::textPosition(); - textFont = ShowFpsConfig::textFont(); - textColor = ShowFpsConfig::textColor(); - double textAlpha = ShowFpsConfig::textAlpha(); - - if (!textColor.isValid()) { - textColor = QPalette().color(QPalette::Active, QPalette::WindowText); - } - textColor.setAlphaF(textAlpha); - - switch (textPosition) { - case TOP_LEFT: - fpsTextRect = QRect(0, 0, 100, 100); - textAlign = Qt::AlignTop | Qt::AlignLeft; - break; - case TOP_RIGHT: - fpsTextRect = QRect(screenSize.width() - 100, 0, 100, 100); - textAlign = Qt::AlignTop | Qt::AlignRight; - break; - case BOTTOM_LEFT: - fpsTextRect = QRect(0, screenSize.height() - 100, 100, 100); - textAlign = Qt::AlignBottom | Qt::AlignLeft; - break; - case BOTTOM_RIGHT: - fpsTextRect = QRect(screenSize.width() - 100, screenSize.height() - 100, 100, 100); - textAlign = Qt::AlignBottom | Qt::AlignRight; - break; - case NOWHERE: - fpsTextRect = QRect(); - break; - case INSIDE_GRAPH: - default: - fpsTextRect = QRect(x, y, FPS_WIDTH + NUM_PAINTS, MAX_TIME); - textAlign = Qt::AlignTop | Qt::AlignRight; - break; - } -} - -void ShowFpsEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) -{ - frames[frames_pos] = QDateTime::currentMSecsSinceEpoch(); - if (++frames_pos == MAX_FPS) { - frames_pos = 0; - } - effects->prePaintScreen(data, presentTime); - data.paint += fps_rect; - - paint_size[paints_pos] = 0; - t.restart(); - - // detect highest monitor refresh rate - int num_screens = effects->screens().size(); - detectedMaxFps = 0; - for (int i = 0; i < num_screens; ++i) { - detectedMaxFps = std::max(effects->screens().at(i)->refreshRate(), detectedMaxFps); - } - detectedMaxFps /= 1000; // convert mHz to Hz (see kwineffects.h: EffectScreen) -} - -void ShowFpsEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) -{ - effects->paintWindow(w, mask, region, data); - - // Take intersection of region and actual window's rect, minus the fps area - // (since we keep repainting it) and count the pixels. - QRegion r2 = region & QRect(w->x(), w->y(), w->width(), w->height()); - r2 -= fps_rect; - int winsize = 0; - for (const QRect &r : r2) { - winsize += r.width() * r.height(); - } - paint_size[paints_pos] += winsize; -} - -void ShowFpsEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) -{ - effects->paintScreen(mask, region, data); - int lastFrame = frames_pos - 1; - if (lastFrame < 0) { - lastFrame = MAX_FPS - 1; - } - const qint64 lastTimestamp = frames[lastFrame]; - int fps = 0; - for (int i = 0; i < MAX_FPS; i++) { - if (abs(lastTimestamp - frames[i]) < 1000) { - ++fps; // count all frames in the last second - } - } - if (effects->isOpenGLCompositing()) { - paintGL(fps, data.projectionMatrix()); - glFinish(); // make sure all rendering is done - } else if (effects->compositingType() == QPainterCompositing) { - paintQPainter(fps); - } - if (m_showNoBenchmark) { - m_noBenchmark->render(infiniteRegion(), 1.0, alpha); - } -} - -void ShowFpsEffect::paintGL(int fps, const QMatrix4x4 &projectionMatrix) -{ - int x = this->x; - int y = this->y; - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - // TODO painting first the background white and then the contents - // means that the contents also blend with the background, I guess - ShaderBinder binder(ShaderTrait::UniformColor); - binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, projectionMatrix); - if (m_showGraph) { - GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer(); - vbo->reset(); - QColor color(255, 255, 255); - color.setAlphaF(alpha); - vbo->setColor(color); - QVector verts; - verts.reserve(12); - verts << x + 2 * NUM_PAINTS + FPS_WIDTH << y; - verts << x << y; - verts << x << y + MAX_TIME; - verts << x << y + MAX_TIME; - verts << x + 2 * NUM_PAINTS + FPS_WIDTH << y + MAX_TIME; - verts << x + 2 * NUM_PAINTS + FPS_WIDTH << y; - vbo->setData(6, 2, verts.constData(), nullptr); - vbo->render(GL_TRIANGLES); - y += MAX_TIME; // paint up from the bottom - color.setRed(0); - color.setGreen(0); - vbo->setColor(color); - verts.clear(); - verts << x + FPS_WIDTH << y - fps; - verts << x << y - fps; - verts << x << y; - verts << x << y; - verts << x + FPS_WIDTH << y; - verts << x + FPS_WIDTH << y - fps; - vbo->setData(6, 2, verts.constData(), nullptr); - vbo->render(GL_TRIANGLES); - - color.setBlue(0); - vbo->setColor(color); - QVector vertices; - for (int i = 10; i < MAX_TIME; i += 10) { - vertices << x << y - i; - vertices << x + FPS_WIDTH << y - i; - } - vbo->setData(vertices.size() / 2, 2, vertices.constData(), nullptr); - vbo->render(GL_LINES); - x += FPS_WIDTH; - - // Paint FPS graph - paintFPSGraph(x, y); - x += NUM_PAINTS; - - // Paint amount of rendered pixels graph - paintDrawSizeGraph(x, y); - } - - // Paint FPS numerical value - if (fpsTextRect.isValid()) { - fpsText.reset(new GLTexture(fpsTextImage(fps))); - fpsText->bind(); - ShaderBinder binder(ShaderTrait::MapTexture); - QMatrix4x4 mvp = projectionMatrix; - mvp.translate(fpsTextRect.x(), fpsTextRect.y()); - binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, mvp); - fpsText->render(fpsTextRect); - fpsText->unbind(); - effects->addRepaint(fpsTextRect); - } - - // Paint paint sizes - glDisable(GL_BLEND); -} - -void ShowFpsEffect::paintQPainter(int fps) -{ - QPainter *painter = effects->scenePainter(); - painter->save(); - - if (m_showGraph) { - QColor color(255, 255, 255); - color.setAlphaF(alpha); - - painter->setCompositionMode(QPainter::CompositionMode_SourceOver); - painter->fillRect(x, y, 2 * NUM_PAINTS + FPS_WIDTH, MAX_TIME, color); - color.setRed(0); - color.setGreen(0); - painter->fillRect(x, y + MAX_TIME - fps, FPS_WIDTH, fps, color); - - color.setBlue(0); - for (int i = 10; i < MAX_TIME; i += 10) { - painter->setPen(color); - painter->drawLine(x, y + MAX_TIME - i, x + FPS_WIDTH, y + MAX_TIME - i); - } - - // Paint FPS graph - paintFPSGraph(x + FPS_WIDTH, y + MAX_TIME - 1); - - // Paint amount of rendered pixels graph - paintDrawSizeGraph(x + FPS_WIDTH + NUM_PAINTS, y + MAX_TIME - 1); - } - - // Paint FPS numerical value - painter->setPen(Qt::black); - painter->drawText(fpsTextRect, textAlign, QString::number(fps)); - - painter->restore(); -} - -void ShowFpsEffect::paintFPSGraph(int x, int y) -{ - // Paint FPS graph - QList lines; - lines << 10 << 20 << 50; - QList values; - for (int i = 0; - i < NUM_PAINTS; - ++i) { - values.append(paints[(i + paints_pos) % NUM_PAINTS]); - } - paintGraph(x, y, values, lines, true); -} - -void ShowFpsEffect::paintDrawSizeGraph(int x, int y) -{ - int max_drawsize = 0; - for (int i = 0; i < NUM_PAINTS; i++) { - max_drawsize = qMax(max_drawsize, paint_size[i]); - } - - // Log of min/max values shown on graph - const float max_pixels_log = 7.2f; - const float min_pixels_log = 2.0f; - const int minh = 5; // Minimum height of the bar when value > 0 - - float drawscale = (MAX_TIME - minh) / (max_pixels_log - min_pixels_log); - QList drawlines; - - for (int logh = (int)min_pixels_log; logh <= max_pixels_log; logh++) { - drawlines.append((int)((logh - min_pixels_log) * drawscale) + minh); - } - - QList drawvalues; - for (int i = 0; - i < NUM_PAINTS; - ++i) { - int value = paint_size[(i + paints_pos) % NUM_PAINTS]; - int h = 0; - if (value > 0) { - h = (int)((log10((double)value) - min_pixels_log) * drawscale); - h = qMin(qMax(0, h) + minh, MAX_TIME); - } - drawvalues.append(h); - } - paintGraph(x, y, drawvalues, drawlines, false); -} - -void ShowFpsEffect::paintGraph(int x, int y, QList values, QList lines, bool colorize) -{ - if (effects->isOpenGLCompositing()) { - QColor color(0, 0, 0); - color.setAlphaF(alpha); - GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer(); - vbo->reset(); - vbo->setColor(color); - QVector verts; - // First draw the lines - for (int h : qAsConst(lines)) { - verts << x << y - h; - verts << x + values.count() << y - h; - } - vbo->setData(verts.size() / 2, 2, verts.constData(), nullptr); - vbo->render(GL_LINES); - // Then the graph values - int lastValue = 0; - verts.clear(); - for (int i = 0; i < values.count(); i++) { - int value = values[i]; - if (colorize && value != lastValue) { - if (!verts.isEmpty()) { - vbo->setData(verts.size() / 2, 2, verts.constData(), nullptr); - vbo->render(GL_LINES); - } - verts.clear(); - if (value <= 10) { - color = QColor(0, 255, 0); - } else if (value <= 20) { - color = QColor(255, 255, 0); - } else if (value <= 50) { - color = QColor(255, 0, 0); - } else { - color = QColor(0, 0, 0); - } - vbo->setColor(color); - } - verts << x + values.count() - i << y; - verts << x + values.count() - i << y - value; - lastValue = value; - } - if (!verts.isEmpty()) { - vbo->setData(verts.size() / 2, 2, verts.constData(), nullptr); - vbo->render(GL_LINES); - } - } else if (effects->compositingType() == QPainterCompositing) { - QPainter *painter = effects->scenePainter(); - painter->setPen(Qt::black); - // First draw the lines - for (int h : qAsConst(lines)) { - painter->drawLine(x, y - h, x + values.count(), y - h); - } - QColor color(0, 0, 0); - color.setAlphaF(alpha); - for (int i = 0; i < values.count(); i++) { - int value = values[i]; - if (colorize) { - if (value <= 10) { - color = QColor(0, 255, 0); - } else if (value <= 20) { - color = QColor(255, 255, 0); - } else if (value <= 50) { - color = QColor(255, 0, 0); - } else { - color = QColor(0, 0, 0); - } - } - painter->setPen(color); - painter->drawLine(x + values.count() - i, y, x + values.count() - i, y - value); - } - } -} - -void ShowFpsEffect::postPaintScreen() -{ - effects->postPaintScreen(); - paints[paints_pos] = t.elapsed(); - if (++paints_pos == NUM_PAINTS) { - paints_pos = 0; - } - effects->addRepaint(fps_rect); -} - -QImage ShowFpsEffect::fpsTextImage(int fps) -{ - QImage im(100, 100, QImage::Format_ARGB32); - im.fill(Qt::transparent); - QPainter painter(&im); - painter.setFont(textFont); - QColor col = textColor; - if (detectedMaxFps > 0) { - fps = std::min(fps, detectedMaxFps); - } - if (m_colorizeText) { - if (fps >= detectedMaxFps * 0.75) { - col = QColor(0, 255, 0); // green - } else if (fps >= detectedMaxFps * 0.5) { - col = QColor(255, 255, 0); // yellow - } else if (fps >= detectedMaxFps * 0.25) { - col = QColor(255, 0, 0); // red - } else { - col = QColor(0, 0, 0); // black - } - } - painter.setPen(col); - painter.drawText(QRect(0, 0, 100, 100), textAlign, QString::number(fps)); - painter.end(); - return im; -} - -} // namespace diff --git a/src/effects/showfps/showfps.h b/src/effects/showfps/showfps.h deleted file mode 100644 index b99db9751b..0000000000 --- a/src/effects/showfps/showfps.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2006 Lubos Lunak - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -#ifndef KWIN_SHOWFPS_H -#define KWIN_SHOWFPS_H - -#include -#include - -#include - -namespace KWin -{ -class GLTexture; - -class ShowFpsEffect - : public Effect -{ - Q_OBJECT - Q_PROPERTY(qreal alpha READ configuredAlpha) - Q_PROPERTY(int x READ configuredX) - Q_PROPERTY(int y READ configuredY) - Q_PROPERTY(QRect fpsTextRect READ configuredFpsTextRect) - Q_PROPERTY(int textAlign READ configuredTextAlign) - Q_PROPERTY(QFont textFont READ configuredTextFont) - Q_PROPERTY(QColor textColor READ configuredTextColor) - Q_PROPERTY(bool showGraph READ configuredShowGraph) - Q_PROPERTY(bool showNoBenchmark READ configuredShowNoBenchmark) - Q_PROPERTY(bool colorizeText READ configuredColorizeText) -public: - ShowFpsEffect(); - ~ShowFpsEffect() override; - - void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; - void paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) override; - void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override; - void postPaintScreen() override; - enum { - INSIDE_GRAPH, - NOWHERE, - TOP_LEFT, - TOP_RIGHT, - BOTTOM_LEFT, - BOTTOM_RIGHT, - }; // fps text position - - // for properties - qreal configuredAlpha() const - { - return alpha; - } - int configuredX() const - { - return x; - } - int configuredY() const - { - return y; - } - QRect configuredFpsTextRect() const - { - return fpsTextRect; - } - int configuredTextAlign() const - { - return textAlign; - } - QFont configuredTextFont() const - { - return textFont; - } - QColor configuredTextColor() const - { - return textColor; - } - bool configuredShowGraph() const - { - return m_showGraph; - } - bool configuredShowNoBenchmark() const - { - return m_showNoBenchmark; - } - bool configuredColorizeText() const - { - return m_colorizeText; - } - -private: - void paintGL(int fps, const QMatrix4x4 &projectionMatrix); - void paintQPainter(int fps); - void paintFPSGraph(int x, int y); - void paintDrawSizeGraph(int x, int y); - void paintGraph(int x, int y, QList values, QList lines, bool colorize); - QImage fpsTextImage(int fps); - QElapsedTimer t; - enum { - NUM_PAINTS = 100, - }; // remember time needed to paint this many paints - int paints[NUM_PAINTS]; // time needed to paint - int paint_size[NUM_PAINTS]; // number of pixels painted - int paints_pos; // position in the queue - enum { - MAX_FPS = 200, - }; - qint64 frames[MAX_FPS]; // the time when the frame was done - int frames_pos; // position in the queue - double alpha; - bool m_showNoBenchmark; - bool m_showGraph; - bool m_colorizeText; - int detectedMaxFps; - int x; - int y; - QRect fps_rect; - std::unique_ptr fpsText; - int textPosition; - QFont textFont; - QColor textColor; - QRect fpsTextRect; - int textAlign; - std::unique_ptr m_noBenchmark; -}; - -} // namespace - -#endif diff --git a/src/effects/showfps/showfps.kcfg b/src/effects/showfps/showfps.kcfg deleted file mode 100644 index c1627eac76..0000000000 --- a/src/effects/showfps/showfps.kcfg +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - 0 - - - - invalid - - - 1.0 - - - 0.5 - - - -10000 - - - 0 - - - true - - - true - - - true - - - diff --git a/src/effects/showfps/showfps_config.cpp b/src/effects/showfps/showfps_config.cpp deleted file mode 100644 index 26c1a44c07..0000000000 --- a/src/effects/showfps/showfps_config.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2007 Rivo Laks - - SPDX-License-Identifier: GPL-2.0-or-later -*/ -#include "showfps_config.h" - -#include - -// KConfigSkeleton -#include "showfpsconfig.h" -#include - -#include -#include - -K_PLUGIN_CLASS(KWin::ShowFpsEffectConfig) - -namespace KWin -{ - -ShowFpsEffectConfig::ShowFpsEffectConfig(QWidget *parent, const QVariantList &args) - : KCModule(parent, args) -{ - m_ui.setupUi(this); - - ShowFpsConfig::instance(KWIN_CONFIG); - addConfig(ShowFpsConfig::self(), this); -} - -void ShowFpsEffectConfig::save() -{ - KCModule::save(); - OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"), - QStringLiteral("/Effects"), - QDBusConnection::sessionBus()); - interface.reconfigureEffect(QStringLiteral("showfps")); -} - -} // namespace - -#include "showfps_config.moc" diff --git a/src/effects/showfps/showfps_config.h b/src/effects/showfps/showfps_config.h deleted file mode 100644 index 7862611393..0000000000 --- a/src/effects/showfps/showfps_config.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2007 Rivo Laks - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -#ifndef KWIN_SHOWFPS_CONFIG_H -#define KWIN_SHOWFPS_CONFIG_H - -#include - -#include "ui_showfps_config.h" - -namespace KWin -{ - -class ShowFpsEffectConfig : public KCModule -{ - Q_OBJECT -public: - explicit ShowFpsEffectConfig(QWidget *parent = nullptr, const QVariantList &args = QVariantList()); - -public Q_SLOTS: - void save() override; - -private: - Ui::ShowFpsEffectConfigForm m_ui; -}; - -} // namespace - -#endif diff --git a/src/effects/showfps/showfps_config.ui b/src/effects/showfps/showfps_config.ui deleted file mode 100644 index 65db6acf39..0000000000 --- a/src/effects/showfps/showfps_config.ui +++ /dev/null @@ -1,230 +0,0 @@ - - - KWin::ShowFpsEffectConfigForm - - - - 0 - 0 - 356 - 250 - - - - - - - Text - - - - - - Text position: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - kcfg_TextPosition - - - - - - - - 0 - 0 - - - - - Inside Graph - - - - - Nowhere - - - - - Top Left - - - - - Top Right - - - - - Bottom Left - - - - - Bottom Right - - - - - - - - Text font: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - - - - - Text color: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - kcfg_TextColor - - - - - - - - 0 - 0 - - - - - - - - Text alpha: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - kcfg_TextAlpha - - - - - - - - 0 - 0 - - - - 2 - - - 1.000000000000000 - - - 0.100000000000000 - - - 1.000000000000000 - - - - - - - Show graph: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - kcfg_ShowGraph - - - - - - - Show on active screen - - - - - - - Show Message: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - kcfg_ShowNoBenchmark - - - - - - - Show "not a benchmark" message - - - - - - - Colorize Text: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - kcfg_ColorizeText - - - - - - - Color text by value (green > yellow > red) - - - - - - - - - - - KColorButton - QPushButton -
kcolorbutton.h
-
- - KFontRequester - QWidget -
kfontrequester.h
-
-
- - -
diff --git a/src/effects/showfps/showfpsconfig.kcfgc b/src/effects/showfps/showfpsconfig.kcfgc deleted file mode 100644 index c08427e13d..0000000000 --- a/src/effects/showfps/showfpsconfig.kcfgc +++ /dev/null @@ -1,5 +0,0 @@ -File=showfps.kcfg -ClassName=ShowFpsConfig -NameSpace=KWin -Singleton=true -Mutators=true diff --git a/src/effects/showfps/showfpseffect.cpp b/src/effects/showfps/showfpseffect.cpp new file mode 100644 index 0000000000..d239009548 --- /dev/null +++ b/src/effects/showfps/showfpseffect.cpp @@ -0,0 +1,126 @@ +/* + SPDX-FileCopyrightText: 2006 Lubos Lunak + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii + SPDX-FileCopyrightText: 2022 Arjen Hiemstra + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "showfpseffect.h" + +#include +#include + +namespace KWin +{ + +ShowFpsEffect::ShowFpsEffect() +{ +} + +ShowFpsEffect::~ShowFpsEffect() = default; + +int ShowFpsEffect::fps() const +{ + return m_fps; +} + +int ShowFpsEffect::maximumFps() const +{ + return m_maximumFps; +} + +int ShowFpsEffect::paintDuration() const +{ + return m_paintDuration; +} + +int ShowFpsEffect::paintAmount() const +{ + return m_paintAmount; +} + +QColor ShowFpsEffect::paintColor() const +{ + auto normalizedDuration = std::min(1.0, m_paintDuration / 100.0); + return QColor::fromHsvF(0.3 - (0.3 * normalizedDuration), 1.0, 1.0); +} + +void ShowFpsEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) +{ + effects->prePaintScreen(data, presentTime); + + m_newFps += 1; + + m_paintDurationTimer.restart(); + m_paintAmount = 0; + + // detect highest monitor refresh rate + int maximumFps = 0; + const auto screens = effects->screens(); + for (auto screen : screens) { + maximumFps = std::max(screen->refreshRate(), maximumFps); + } + maximumFps /= 1000; // Convert from mHz to Hz. + + if (maximumFps != m_maximumFps) { + m_maximumFps = maximumFps; + Q_EMIT maximumFpsChanged(); + } + + if (!m_scene) { + m_window = std::make_unique(); + m_window->create(); + m_scene = std::make_unique(nullptr, m_window.get()); + const auto url = QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/effects/showfps/qml/main.qml"))); + m_scene->setSource(url, {{QStringLiteral("effect"), QVariant::fromValue(this)}}); + } + + const auto rect = effects->renderTargetRect(); + m_scene->setGeometry(QRect(rect.x() + rect.width() - 300, 0, 300, 150)); +} + +void ShowFpsEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) +{ + effects->paintScreen(mask, region, data); + + auto now = std::chrono::steady_clock::now(); + if ((now - m_lastFpsTime) >= std::chrono::milliseconds(1000)) { + m_fps = m_newFps; + m_newFps = 0; + m_lastFpsTime = now; + Q_EMIT fpsChanged(); + } + + effects->renderOffscreenQuickView(m_scene.get()); +} + +void ShowFpsEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) +{ + effects->paintWindow(w, mask, region, data); + + // Take intersection of region and actual window's rect, minus the fps area + // (since we keep repainting it) and count the pixels. + QRegion repaintRegion = region & w->frameGeometry().toRect(); + repaintRegion -= m_scene->geometry(); + for (const QRect &rect : repaintRegion) { + m_paintAmount += rect.width() * rect.height(); + } +} + +void ShowFpsEffect::postPaintScreen() +{ + effects->postPaintScreen(); + + m_paintDuration = m_paintDurationTimer.elapsed(); + Q_EMIT paintChanged(); + + effects->addRepaint(m_scene->geometry()); +} + +bool ShowFpsEffect::supported() +{ + return effects->isOpenGLCompositing(); +} + +} // namespace KWin diff --git a/src/effects/showfps/showfpseffect.h b/src/effects/showfps/showfpseffect.h new file mode 100644 index 0000000000..988a66ae0d --- /dev/null +++ b/src/effects/showfps/showfpseffect.h @@ -0,0 +1,65 @@ +/* + SPDX-FileCopyrightText: 2006 Lubos Lunak + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii + SPDX-FileCopyrightText: 2022 Arjen Hiemstra + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#pragma once + +#include +#include + +#include + +namespace KWin +{ + +class ShowFpsEffect : public Effect +{ + Q_OBJECT + Q_PROPERTY(int fps READ fps NOTIFY fpsChanged) + Q_PROPERTY(int maximumFps READ maximumFps NOTIFY maximumFpsChanged) + Q_PROPERTY(int paintDuration READ paintDuration NOTIFY paintChanged) + Q_PROPERTY(int paintAmount READ paintAmount NOTIFY paintChanged) + Q_PROPERTY(QColor paintColor READ paintColor NOTIFY paintChanged) + +public: + ShowFpsEffect(); + ~ShowFpsEffect() override; + + int fps() const; + int maximumFps() const; + int paintDuration() const; + int paintAmount() const; + QColor paintColor() const; + + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; + void paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) override; + void paintWindow(KWin::EffectWindow *w, int mask, QRegion region, KWin::WindowPaintData &data) override; + void postPaintScreen() override; + + static bool supported(); + +Q_SIGNALS: + void fpsChanged(); + void maximumFpsChanged(); + void paintChanged(); + +private: + std::unique_ptr m_window; + std::unique_ptr m_scene; + + int m_maximumFps = 0; + + int m_fps = 0; + int m_newFps = 0; + std::chrono::steady_clock::time_point m_lastFpsTime; + + int m_paintDuration = 0; + int m_paintAmount = 0; + QElapsedTimer m_paintDurationTimer; +}; + +} // namespace KWin