effects/showfps: add new options

- added option to remove the frametime graph
- added option to remove the "this is a benchmark" message
- location of the fps counter is now on the "active" monitor by default
- removed the hard-limit of 100 for the FPS counter
- added option to color the text based off the FPS value
This commit is contained in:
Gustavo Silvera 2022-04-04 16:05:56 +00:00 committed by Xaver Hugl
parent 9de9b93325
commit 41526bd8dd
7 changed files with 200 additions and 71 deletions

View file

@ -1895,6 +1895,11 @@ QRect EffectScreenImpl::geometry() const
return m_platformOutput->geometry(); return m_platformOutput->geometry();
} }
int EffectScreenImpl::refreshRate() const
{
return m_platformOutput->refreshRate();
}
EffectScreen::Transform EffectScreenImpl::transform() const EffectScreen::Transform EffectScreenImpl::transform() const
{ {
return EffectScreen::Transform(m_platformOutput->transform()); return EffectScreen::Transform(m_platformOutput->transform());

View file

@ -390,6 +390,7 @@ public:
QString name() const override; QString name() const override;
qreal devicePixelRatio() const override; qreal devicePixelRatio() const override;
QRect geometry() const override; QRect geometry() const override;
int refreshRate() const override;
Transform transform() const override; Transform transform() const override;
static EffectScreenImpl *get(AbstractOutput *output); static EffectScreenImpl *get(AbstractOutput *output);

View file

@ -47,8 +47,10 @@ ShowFpsEffect::ShowFpsEffect()
++i) { ++i) {
frames[i] = 0; frames[i] = 0;
} }
m_noBenchmark->setAlignment(Qt::AlignTop | Qt::AlignRight); if (m_showNoBenchmark) {
m_noBenchmark->setText(i18n("This effect is not a benchmark")); m_noBenchmark->setAlignment(Qt::AlignTop | Qt::AlignRight);
m_noBenchmark->setText(i18n("This effect is not a benchmark"));
}
reconfigure(ReconfigureAll); reconfigure(ReconfigureAll);
} }
@ -62,6 +64,9 @@ void ShowFpsEffect::reconfigure(ReconfigureFlags)
alpha = ShowFpsConfig::alpha(); alpha = ShowFpsConfig::alpha();
x = ShowFpsConfig::x(); x = ShowFpsConfig::x();
y = ShowFpsConfig::y(); y = ShowFpsConfig::y();
m_showNoBenchmark = ShowFpsConfig::showNoBenchmark();
m_showGraph = ShowFpsConfig::showGraph();
m_colorizeText = ShowFpsConfig::colorizeText();
const QSize screenSize = effects->virtualScreenSize(); const QSize screenSize = effects->virtualScreenSize();
if (x == -10000) { // there's no -0 :( if (x == -10000) { // there's no -0 :(
x = screenSize.width() - 2 * NUM_PAINTS - FPS_WIDTH; x = screenSize.width() - 2 * NUM_PAINTS - FPS_WIDTH;
@ -125,6 +130,14 @@ void ShowFpsEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::millis
paint_size[paints_pos] = 0; paint_size[paints_pos] = 0;
t.restart(); 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) void ShowFpsEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data)
@ -158,16 +171,15 @@ void ShowFpsEffect::paintScreen(int mask, const QRegion &region, ScreenPaintData
++fps; // count all frames in the last second ++fps; // count all frames in the last second
} }
} }
if (fps > MAX_TIME) {
fps = MAX_TIME; // keep it the same height
}
if (effects->isOpenGLCompositing()) { if (effects->isOpenGLCompositing()) {
paintGL(fps, data.projectionMatrix()); paintGL(fps, data.projectionMatrix());
glFinish(); // make sure all rendering is done glFinish(); // make sure all rendering is done
} else if (effects->compositingType() == QPainterCompositing) { } else if (effects->compositingType() == QPainterCompositing) {
paintQPainter(fps); paintQPainter(fps);
} }
m_noBenchmark->render(infiniteRegion(), 1.0, alpha); if (m_showNoBenchmark) {
m_noBenchmark->render(infiniteRegion(), 1.0, alpha);
}
} }
void ShowFpsEffect::paintGL(int fps, const QMatrix4x4 &projectionMatrix) void ShowFpsEffect::paintGL(int fps, const QMatrix4x4 &projectionMatrix)
@ -180,54 +192,54 @@ void ShowFpsEffect::paintGL(int fps, const QMatrix4x4 &projectionMatrix)
// means that the contents also blend with the background, I guess // means that the contents also blend with the background, I guess
ShaderBinder binder(ShaderTrait::UniformColor); ShaderBinder binder(ShaderTrait::UniformColor);
binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, projectionMatrix); binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, projectionMatrix);
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer(); if (m_showGraph) {
vbo->reset(); GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
QColor color(255, 255, 255); vbo->reset();
color.setAlphaF(alpha); QColor color(255, 255, 255);
vbo->setColor(color); color.setAlphaF(alpha);
QVector<float> verts; vbo->setColor(color);
verts.reserve(12); QVector<float> verts;
verts << x + 2 * NUM_PAINTS + FPS_WIDTH << y; verts.reserve(12);
verts << x << y; verts << x + 2 * NUM_PAINTS + FPS_WIDTH << y;
verts << x << y + MAX_TIME; 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 << y + MAX_TIME;
verts << x + 2 * NUM_PAINTS + FPS_WIDTH << y; verts << x + 2 * NUM_PAINTS + FPS_WIDTH << y + MAX_TIME;
vbo->setData(6, 2, verts.constData(), nullptr); verts << x + 2 * NUM_PAINTS + FPS_WIDTH << y;
vbo->render(GL_TRIANGLES); vbo->setData(6, 2, verts.constData(), nullptr);
y += MAX_TIME; // paint up from the bottom vbo->render(GL_TRIANGLES);
color.setRed(0); y += MAX_TIME; // paint up from the bottom
color.setGreen(0); color.setRed(0);
vbo->setColor(color); color.setGreen(0);
verts.clear(); vbo->setColor(color);
verts << x + FPS_WIDTH << y - fps; verts.clear();
verts << x << y - fps; verts << x + FPS_WIDTH << y - fps;
verts << x << y; verts << x << y - fps;
verts << x << y; verts << x << y;
verts << x + FPS_WIDTH << y; verts << x << y;
verts << x + FPS_WIDTH << y - fps; verts << x + FPS_WIDTH << y;
vbo->setData(6, 2, verts.constData(), nullptr); verts << x + FPS_WIDTH << y - fps;
vbo->render(GL_TRIANGLES); vbo->setData(6, 2, verts.constData(), nullptr);
vbo->render(GL_TRIANGLES);
color.setBlue(0); color.setBlue(0);
vbo->setColor(color); vbo->setColor(color);
QVector<float> vertices; QVector<float> vertices;
for (int i = 10; for (int i = 10; i < MAX_TIME; i += 10) {
i < MAX_TIME; vertices << x << y - i;
i += 10) { vertices << x + FPS_WIDTH << y - i;
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);
} }
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 // Paint FPS numerical value
if (fpsTextRect.isValid()) { if (fpsTextRect.isValid()) {
@ -251,27 +263,29 @@ void ShowFpsEffect::paintQPainter(int fps)
QPainter *painter = effects->scenePainter(); QPainter *painter = effects->scenePainter();
painter->save(); painter->save();
QColor color(255, 255, 255); if (m_showGraph) {
color.setAlphaF(alpha); QColor color(255, 255, 255);
color.setAlphaF(alpha);
painter->setCompositionMode(QPainter::CompositionMode_SourceOver); painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
painter->fillRect(x, y, 2 * NUM_PAINTS + FPS_WIDTH, MAX_TIME, color); painter->fillRect(x, y, 2 * NUM_PAINTS + FPS_WIDTH, MAX_TIME, color);
color.setRed(0); color.setRed(0);
color.setGreen(0); color.setGreen(0);
painter->fillRect(x, y + MAX_TIME - fps, FPS_WIDTH, fps, color); painter->fillRect(x, y + MAX_TIME - fps, FPS_WIDTH, fps, color);
color.setBlue(0); color.setBlue(0);
for (int i = 10; i < MAX_TIME; i += 10) { for (int i = 10; i < MAX_TIME; i += 10) {
painter->setPen(color); painter->setPen(color);
painter->drawLine(x, y + MAX_TIME - i, x + FPS_WIDTH, y + MAX_TIME - i); 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 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 // Paint FPS numerical value
painter->setPen(Qt::black); painter->setPen(Qt::black);
painter->drawText(fpsTextRect, textAlign, QString::number(fps)); painter->drawText(fpsTextRect, textAlign, QString::number(fps));
@ -417,7 +431,22 @@ QImage ShowFpsEffect::fpsTextImage(int fps)
im.fill(Qt::transparent); im.fill(Qt::transparent);
QPainter painter(&im); QPainter painter(&im);
painter.setFont(textFont); painter.setFont(textFont);
painter.setPen(textColor); 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.drawText(QRect(0, 0, 100, 100), textAlign, QString::number(fps));
painter.end(); painter.end();
return im; return im;

View file

@ -30,6 +30,9 @@ class ShowFpsEffect
Q_PROPERTY(int textAlign READ configuredTextAlign) Q_PROPERTY(int textAlign READ configuredTextAlign)
Q_PROPERTY(QFont textFont READ configuredTextFont) Q_PROPERTY(QFont textFont READ configuredTextFont)
Q_PROPERTY(QColor textColor READ configuredTextColor) 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: public:
ShowFpsEffect(); ShowFpsEffect();
~ShowFpsEffect() override; ~ShowFpsEffect() override;
@ -77,6 +80,18 @@ public:
{ {
return textColor; return textColor;
} }
bool configuredShowGraph() const
{
return m_showGraph;
}
bool configuredShowNoBenchmark() const
{
return m_showNoBenchmark;
}
bool configuredColorizeText() const
{
return m_colorizeText;
}
private: private:
void paintGL(int fps, const QMatrix4x4 &projectionMatrix); void paintGL(int fps, const QMatrix4x4 &projectionMatrix);
@ -98,6 +113,10 @@ private:
qint64 frames[MAX_FPS]; // the time when the frame was done qint64 frames[MAX_FPS]; // the time when the frame was done
int frames_pos; // position in the queue int frames_pos; // position in the queue
double alpha; double alpha;
bool m_showNoBenchmark;
bool m_showGraph;
bool m_colorizeText;
int detectedMaxFps;
int x; int x;
int y; int y;
QRect fps_rect; QRect fps_rect;

View file

@ -24,5 +24,14 @@
<entry name="Y" type="Int"> <entry name="Y" type="Int">
<default>0</default> <default>0</default>
</entry> </entry>
<entry name="ShowGraph" type="Bool">
<default>true</default>
</entry>
<entry name="ShowNoBenchmark" type="Bool">
<default>true</default>
</entry>
<entry name="ColorizeText" type="Bool">
<default>true</default>
</entry>
</group> </group>
</kcfg> </kcfg>

View file

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>356</width> <width>356</width>
<height>180</height> <height>250</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout"> <layout class="QVBoxLayout">
@ -148,6 +148,66 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Show graph:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>kcfg_ShowGraph</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="kcfg_ShowGraph">
<property name="text">
<string>Show on active screen</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Show Message:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>kcfg_ShowNoBenchmark</cstring>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="kcfg_ShowNoBenchmark">
<property name="text">
<string>Show "not a benchmark" message</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Colorize Text:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>kcfg_ColorizeText</cstring>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="kcfg_ColorizeText">
<property name="text">
<string>Color text by value (green > yellow > red)</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View file

@ -1954,6 +1954,7 @@ class KWINEFFECTS_EXPORT EffectScreen : public QObject
Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged) Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged)
Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio NOTIFY devicePixelRatioChanged) Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio NOTIFY devicePixelRatioChanged)
Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(qreal refreshRate READ refreshRate CONSTANT)
public: public:
explicit EffectScreen(QObject *parent = nullptr); explicit EffectScreen(QObject *parent = nullptr);
@ -1973,6 +1974,11 @@ public:
*/ */
virtual QRect geometry() const = 0; virtual QRect geometry() const = 0;
/**
* Returns the screen's refresh rate in milli-hertz.
*/
virtual int refreshRate() const = 0;
enum class Transform { enum class Transform {
Normal, Normal,
Rotated90, Rotated90,