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();
}
int EffectScreenImpl::refreshRate() const
{
return m_platformOutput->refreshRate();
}
EffectScreen::Transform EffectScreenImpl::transform() const
{
return EffectScreen::Transform(m_platformOutput->transform());

View file

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

View file

@ -47,8 +47,10 @@ ShowFpsEffect::ShowFpsEffect()
++i) {
frames[i] = 0;
}
m_noBenchmark->setAlignment(Qt::AlignTop | Qt::AlignRight);
m_noBenchmark->setText(i18n("This effect is not a benchmark"));
if (m_showNoBenchmark) {
m_noBenchmark->setAlignment(Qt::AlignTop | Qt::AlignRight);
m_noBenchmark->setText(i18n("This effect is not a benchmark"));
}
reconfigure(ReconfigureAll);
}
@ -62,6 +64,9 @@ void ShowFpsEffect::reconfigure(ReconfigureFlags)
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;
@ -125,6 +130,14 @@ void ShowFpsEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::millis
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)
@ -158,16 +171,15 @@ void ShowFpsEffect::paintScreen(int mask, const QRegion &region, ScreenPaintData
++fps; // count all frames in the last second
}
}
if (fps > MAX_TIME) {
fps = MAX_TIME; // keep it the same height
}
if (effects->isOpenGLCompositing()) {
paintGL(fps, data.projectionMatrix());
glFinish(); // make sure all rendering is done
} else if (effects->compositingType() == QPainterCompositing) {
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)
@ -180,54 +192,54 @@ void ShowFpsEffect::paintGL(int fps, const QMatrix4x4 &projectionMatrix)
// means that the contents also blend with the background, I guess
ShaderBinder binder(ShaderTrait::UniformColor);
binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, projectionMatrix);
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
vbo->reset();
QColor color(255, 255, 255);
color.setAlphaF(alpha);
vbo->setColor(color);
QVector<float> 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);
if (m_showGraph) {
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
vbo->reset();
QColor color(255, 255, 255);
color.setAlphaF(alpha);
vbo->setColor(color);
QVector<float> 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<float> vertices;
for (int i = 10;
i < MAX_TIME;
i += 10) {
vertices << x << y - i;
vertices << x + FPS_WIDTH << y - i;
color.setBlue(0);
vbo->setColor(color);
QVector<float> 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);
}
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()) {
@ -251,27 +263,29 @@ void ShowFpsEffect::paintQPainter(int fps)
QPainter *painter = effects->scenePainter();
painter->save();
QColor color(255, 255, 255);
color.setAlphaF(alpha);
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);
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);
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 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));
@ -417,7 +431,22 @@ QImage ShowFpsEffect::fpsTextImage(int fps)
im.fill(Qt::transparent);
QPainter painter(&im);
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.end();
return im;

View file

@ -30,6 +30,9 @@ class ShowFpsEffect
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;
@ -77,6 +80,18 @@ public:
{
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);
@ -98,6 +113,10 @@ private:
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;

View file

@ -24,5 +24,14 @@
<entry name="Y" type="Int">
<default>0</default>
</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>
</kcfg>

View file

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>356</width>
<height>180</height>
<height>250</height>
</rect>
</property>
<layout class="QVBoxLayout">
@ -148,6 +148,66 @@
</property>
</widget>
</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>
</widget>
</item>

View file

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