2007-11-27 19:40:25 +00:00
|
|
|
/********************************************************************
|
2007-04-29 17:35:43 +00:00
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
|
|
|
|
|
|
|
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
|
|
|
|
|
2007-11-27 19:40:25 +00:00
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
*********************************************************************/
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
#include "showfps.h"
|
|
|
|
|
2012-09-12 17:20:43 +00:00
|
|
|
// KConfigSkeleton
|
|
|
|
#include "showfpsconfig.h"
|
2007-05-13 17:47:20 +00:00
|
|
|
|
2012-09-12 17:20:43 +00:00
|
|
|
#include <kwinconfig.h>
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-08 18:02:23 +00:00
|
|
|
#include <kwinglutils.h>
|
2007-12-17 14:14:53 +00:00
|
|
|
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
2008-05-08 10:08:10 +00:00
|
|
|
#include <kwinxrenderutils.h>
|
2013-01-29 08:18:06 +00:00
|
|
|
#include <xcb/render.h>
|
|
|
|
#endif
|
2008-05-08 10:08:10 +00:00
|
|
|
|
2014-03-17 15:24:10 +00:00
|
|
|
#include <KLocalizedString>
|
2007-09-06 15:02:59 +00:00
|
|
|
#include <math.h>
|
2008-02-05 17:20:08 +00:00
|
|
|
#include <QPainter>
|
2011-01-06 10:58:03 +00:00
|
|
|
#include <QVector2D>
|
2017-11-08 10:23:00 +00:00
|
|
|
#include <QPalette>
|
2007-09-06 15:02:59 +00:00
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
|
|
|
const int FPS_WIDTH = 10;
|
|
|
|
const int MAX_TIME = 100;
|
|
|
|
|
|
|
|
ShowFpsEffect::ShowFpsEffect()
|
2011-01-30 14:34:42 +00:00
|
|
|
: paints_pos(0)
|
|
|
|
, frames_pos(0)
|
2013-04-05 14:22:53 +00:00
|
|
|
, m_noBenchmark(effects->effectFrame(EffectFrameUnstyled, false))
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2016-12-02 19:27:43 +00:00
|
|
|
initConfig<ShowFpsConfig>();
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0;
|
|
|
|
i < NUM_PAINTS;
|
|
|
|
++i) {
|
2007-04-29 17:35:43 +00:00
|
|
|
paints[ i ] = 0;
|
2007-09-06 15:02:59 +00:00
|
|
|
paint_size[ i ] = 0;
|
2008-10-02 09:27:32 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0;
|
|
|
|
i < MAX_FPS;
|
|
|
|
++i)
|
|
|
|
frames[ i ] = 0;
|
2013-04-05 14:22:53 +00:00
|
|
|
m_noBenchmark->setAlignment(Qt::AlignTop | Qt::AlignRight);
|
|
|
|
m_noBenchmark->setText(i18n("This effect is not a benchmark"));
|
2011-01-30 14:34:42 +00:00
|
|
|
reconfigure(ReconfigureAll);
|
|
|
|
}
|
2008-10-02 09:27:32 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void ShowFpsEffect::reconfigure(ReconfigureFlags)
|
|
|
|
{
|
2014-03-25 15:29:03 +00:00
|
|
|
ShowFpsConfig::self()->read();
|
2012-09-12 17:20:43 +00:00
|
|
|
alpha = ShowFpsConfig::alpha();
|
|
|
|
x = ShowFpsConfig::x();
|
|
|
|
y = ShowFpsConfig::y();
|
2014-02-24 15:13:30 +00:00
|
|
|
const QSize screenSize = effects->virtualScreenSize();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (x == -10000) // there's no -0 :(
|
2014-02-24 15:13:30 +00:00
|
|
|
x = screenSize.width() - 2 * NUM_PAINTS - FPS_WIDTH;
|
2011-01-30 14:34:42 +00:00
|
|
|
else if (x < 0)
|
2014-02-24 15:13:30 +00:00
|
|
|
x = screenSize.width() - 2 * NUM_PAINTS - FPS_WIDTH - x;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (y == -10000)
|
2014-02-24 15:13:30 +00:00
|
|
|
y = screenSize.height() - MAX_TIME;
|
2011-01-30 14:34:42 +00:00
|
|
|
else if (y < 0)
|
2014-02-24 15:13:30 +00:00
|
|
|
y = screenSize.height() - MAX_TIME - y;
|
2011-01-30 14:34:42 +00:00
|
|
|
fps_rect = QRect(x, y, FPS_WIDTH + 2 * NUM_PAINTS, MAX_TIME);
|
2013-04-05 14:22:53 +00:00
|
|
|
m_noBenchmark->setPosition(fps_rect.bottomRight() + QPoint(-6, 6));
|
2011-01-30 14:34:42 +00:00
|
|
|
|
2012-09-12 17:20:43 +00:00
|
|
|
int textPosition = ShowFpsConfig::textPosition();
|
|
|
|
textFont = ShowFpsConfig::textFont();
|
|
|
|
textColor = ShowFpsConfig::textColor();
|
|
|
|
double textAlpha = ShowFpsConfig::textAlpha();
|
2011-01-30 14:34:42 +00:00
|
|
|
|
|
|
|
if (!textColor.isValid())
|
2008-02-05 17:20:08 +00:00
|
|
|
textColor = QPalette().color(QPalette::Active, QPalette::WindowText);
|
|
|
|
textColor.setAlphaF(textAlpha);
|
2011-01-30 14:34:42 +00:00
|
|
|
|
|
|
|
switch(textPosition) {
|
|
|
|
case TOP_LEFT:
|
|
|
|
fpsTextRect = QRect(0, 0, 100, 100);
|
|
|
|
textAlign = Qt::AlignTop | Qt::AlignLeft;
|
|
|
|
break;
|
|
|
|
case TOP_RIGHT:
|
2014-02-24 15:13:30 +00:00
|
|
|
fpsTextRect = QRect(screenSize.width() - 100, 0, 100, 100);
|
2011-01-30 14:34:42 +00:00
|
|
|
textAlign = Qt::AlignTop | Qt::AlignRight;
|
|
|
|
break;
|
|
|
|
case BOTTOM_LEFT:
|
2014-02-24 15:13:30 +00:00
|
|
|
fpsTextRect = QRect(0, screenSize.height() - 100, 100, 100);
|
2011-01-30 14:34:42 +00:00
|
|
|
textAlign = Qt::AlignBottom | Qt::AlignLeft;
|
|
|
|
break;
|
|
|
|
case BOTTOM_RIGHT:
|
2014-02-24 15:13:30 +00:00
|
|
|
fpsTextRect = QRect(screenSize.width() - 100, screenSize.height() - 100, 100, 100);
|
2011-01-30 14:34:42 +00:00
|
|
|
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;
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ShowFpsEffect::prePaintScreen(ScreenPrePaintData& data, int time)
|
|
|
|
{
|
|
|
|
if (time == 0) {
|
2007-04-29 17:35:43 +00:00
|
|
|
// TODO optimized away
|
|
|
|
}
|
|
|
|
t.start();
|
|
|
|
frames[ frames_pos ] = t.minute() * 60000 + t.second() * 1000 + t.msec();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (++frames_pos == MAX_FPS)
|
2007-04-29 17:35:43 +00:00
|
|
|
frames_pos = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->prePaintScreen(data, time);
|
2007-09-06 15:02:59 +00:00
|
|
|
data.paint += fps_rect;
|
|
|
|
|
|
|
|
paint_size[ paints_pos ] = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-09-06 15:02:59 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void ShowFpsEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data)
|
|
|
|
{
|
|
|
|
effects->paintWindow(w, mask, region, data);
|
2007-09-06 15:02:59 +00:00
|
|
|
|
|
|
|
// Take intersection of region and actual window's rect, minus the fps area
|
|
|
|
// (since we keep repainting it) and count the pixels.
|
2011-01-30 14:34:42 +00:00
|
|
|
QRegion r2 = region & QRect(w->x(), w->y(), w->width(), w->height());
|
2007-09-06 15:02:59 +00:00
|
|
|
r2 -= fps_rect;
|
|
|
|
int winsize = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (const QRect & r, r2.rects())
|
|
|
|
winsize += r.width() * r.height();
|
2007-09-06 15:02:59 +00:00
|
|
|
paint_size[ paints_pos ] += winsize;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void ShowFpsEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data)
|
|
|
|
{
|
|
|
|
effects->paintScreen(mask, region, data);
|
2007-04-29 17:35:43 +00:00
|
|
|
int fps = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0;
|
|
|
|
i < MAX_FPS;
|
|
|
|
++i)
|
|
|
|
if (abs(t.minute() * 60000 + t.second() * 1000 + t.msec() - frames[ i ]) < 1000)
|
2007-04-29 17:35:43 +00:00
|
|
|
++fps; // count all frames in the last second
|
2011-01-30 14:34:42 +00:00
|
|
|
if (fps > MAX_TIME)
|
2007-04-29 17:35:43 +00:00
|
|
|
fps = MAX_TIME; // keep it the same height
|
2012-09-20 09:33:32 +00:00
|
|
|
if (effects->isOpenGLCompositing()) {
|
2015-11-26 15:22:01 +00:00
|
|
|
paintGL(fps, data.projectionMatrix());
|
2007-04-29 17:35:43 +00:00
|
|
|
glFinish(); // make sure all rendering is done
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-12-17 14:14:53 +00:00
|
|
|
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
2011-01-30 14:34:42 +00:00
|
|
|
if (effects->compositingType() == XRenderCompositing) {
|
|
|
|
paintXrender(fps);
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_flush(xcbConnection()); // make sure all rendering is done
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
#endif
|
2013-06-21 12:17:32 +00:00
|
|
|
if (effects->compositingType() == QPainterCompositing) {
|
|
|
|
paintQPainter(fps);
|
|
|
|
}
|
2013-04-05 14:22:53 +00:00
|
|
|
m_noBenchmark->render(infiniteRegion(), 1.0, alpha);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2015-11-26 15:22:01 +00:00
|
|
|
void ShowFpsEffect::paintGL(int fps, const QMatrix4x4 &projectionMatrix)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
int x = this->x;
|
|
|
|
int y = this->y;
|
2011-01-30 14:34:42 +00:00
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2007-04-29 17:35:43 +00:00
|
|
|
// TODO painting first the background white and then the contents
|
|
|
|
// means that the contents also blend with the background, I guess
|
2015-11-26 15:22:01 +00:00
|
|
|
ShaderBinder binder(ShaderTrait::UniformColor);
|
|
|
|
binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, projectionMatrix);
|
2011-01-06 10:58:03 +00:00
|
|
|
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
|
|
|
|
vbo->reset();
|
|
|
|
QColor color(255, 255, 255);
|
|
|
|
color.setAlphaF(alpha);
|
|
|
|
vbo->setColor(color);
|
|
|
|
QVector<float> verts;
|
|
|
|
verts.reserve(12);
|
2011-01-30 14:34:42 +00:00
|
|
|
verts << x + 2 * NUM_PAINTS + FPS_WIDTH << y;
|
2011-01-06 10:58:03 +00:00
|
|
|
verts << x << y;
|
|
|
|
verts << x << y + MAX_TIME;
|
|
|
|
verts << x << y + MAX_TIME;
|
2011-01-30 14:34:42 +00:00
|
|
|
verts << x + 2 * NUM_PAINTS + FPS_WIDTH << y + MAX_TIME;
|
|
|
|
verts << x + 2 * NUM_PAINTS + FPS_WIDTH << y;
|
2011-01-06 10:58:03 +00:00
|
|
|
vbo->setData(6, 2, verts.constData(), NULL);
|
|
|
|
vbo->render(GL_TRIANGLES);
|
2007-04-29 17:35:43 +00:00
|
|
|
y += MAX_TIME; // paint up from the bottom
|
2011-01-06 10:58:03 +00:00
|
|
|
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(), NULL);
|
|
|
|
vbo->render(GL_TRIANGLES);
|
|
|
|
|
|
|
|
|
|
|
|
color.setBlue(0);
|
|
|
|
vbo->setColor(color);
|
|
|
|
QVector<float> vertices;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 10;
|
|
|
|
i < MAX_TIME;
|
|
|
|
i += 10) {
|
2011-01-06 10:58:03 +00:00
|
|
|
vertices << x << y - i;
|
|
|
|
vertices << x + FPS_WIDTH << y - i;
|
2007-09-06 15:02:59 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
vbo->setData(vertices.size() / 2, 2, vertices.constData(), NULL);
|
2011-01-06 10:58:03 +00:00
|
|
|
vbo->render(GL_LINES);
|
2007-04-29 17:35:43 +00:00
|
|
|
x += FPS_WIDTH;
|
2007-09-06 15:02:59 +00:00
|
|
|
|
|
|
|
// Paint FPS graph
|
2011-01-30 14:34:42 +00:00
|
|
|
paintFPSGraph(x, y);
|
2007-09-06 15:02:59 +00:00
|
|
|
x += NUM_PAINTS;
|
|
|
|
|
|
|
|
// Paint amount of rendered pixels graph
|
2011-01-30 14:34:42 +00:00
|
|
|
paintDrawSizeGraph(x, y);
|
|
|
|
|
2008-02-05 17:20:08 +00:00
|
|
|
// Paint FPS numerical value
|
2013-08-04 12:50:38 +00:00
|
|
|
if (fpsTextRect.isValid()) {
|
2013-10-06 20:58:20 +00:00
|
|
|
fpsText.reset(new GLTexture(fpsTextImage(fps)));
|
2013-08-04 12:50:38 +00:00
|
|
|
fpsText->bind();
|
2015-11-26 15:22:01 +00:00
|
|
|
ShaderBinder binder(ShaderTrait::MapTexture);
|
|
|
|
QMatrix4x4 mvp = projectionMatrix;
|
|
|
|
mvp.translate(fpsTextRect.x(), fpsTextRect.y());
|
|
|
|
binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, mvp);
|
2013-08-04 12:50:38 +00:00
|
|
|
fpsText->render(QRegion(fpsTextRect), fpsTextRect);
|
|
|
|
fpsText->unbind();
|
|
|
|
effects->addRepaint(fpsTextRect);
|
|
|
|
}
|
2007-09-06 15:02:59 +00:00
|
|
|
|
|
|
|
// Paint paint sizes
|
2011-01-06 10:58:03 +00:00
|
|
|
glDisable(GL_BLEND);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2008-06-06 11:07:15 +00:00
|
|
|
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
2007-04-29 17:35:43 +00:00
|
|
|
/*
|
|
|
|
Differences between OpenGL and XRender:
|
2007-05-08 22:05:30 +00:00
|
|
|
- differently specified rectangles (X: width/height, O: x2,y2)
|
2007-04-29 17:35:43 +00:00
|
|
|
- XRender uses pre-multiplied alpha
|
|
|
|
*/
|
2011-01-30 14:34:42 +00:00
|
|
|
void ShowFpsEffect::paintXrender(int fps)
|
|
|
|
{
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_pixmap_t pixmap = xcb_generate_id(xcbConnection());
|
|
|
|
xcb_create_pixmap(xcbConnection(), 32, pixmap, x11RootWindow(), FPS_WIDTH, MAX_TIME);
|
2011-01-30 14:34:42 +00:00
|
|
|
XRenderPicture p(pixmap, 32);
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_free_pixmap(xcbConnection(), pixmap);
|
2013-01-29 08:18:06 +00:00
|
|
|
xcb_render_color_t col;
|
2011-01-30 14:34:42 +00:00
|
|
|
col.alpha = int(alpha * 0xffff);
|
|
|
|
col.red = int(alpha * 0xffff); // white
|
|
|
|
col.green = int(alpha * 0xffff);
|
|
|
|
col.blue = int(alpha * 0xffff);
|
2013-01-29 08:18:06 +00:00
|
|
|
xcb_rectangle_t rect = {0, 0, FPS_WIDTH, MAX_TIME};
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_render_fill_rectangles(xcbConnection(), XCB_RENDER_PICT_OP_SRC, p, col, 1, &rect);
|
2007-04-29 17:35:43 +00:00
|
|
|
col.red = 0; // blue
|
|
|
|
col.green = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
col.blue = int(alpha * 0xffff);
|
2013-01-29 08:18:06 +00:00
|
|
|
rect.y = MAX_TIME - fps;
|
|
|
|
rect.width = FPS_WIDTH;
|
|
|
|
rect.height = fps;
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_render_fill_rectangles(xcbConnection(), XCB_RENDER_PICT_OP_SRC, p, col, 1, &rect);
|
2007-04-29 17:35:43 +00:00
|
|
|
col.red = 0; // black
|
|
|
|
col.green = 0;
|
|
|
|
col.blue = 0;
|
2013-01-29 08:18:06 +00:00
|
|
|
QVector<xcb_rectangle_t> rects;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 10;
|
|
|
|
i < MAX_TIME;
|
|
|
|
i += 10) {
|
2013-01-29 08:18:06 +00:00
|
|
|
xcb_rectangle_t rect = {0, int16_t(MAX_TIME - i), uint16_t(FPS_WIDTH), 1};
|
|
|
|
rects << rect;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_render_fill_rectangles(xcbConnection(), XCB_RENDER_PICT_OP_SRC, p, col, rects.count(), rects.constData());
|
|
|
|
xcb_render_composite(xcbConnection(), alpha != 1.0 ? XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC, p, XCB_RENDER_PICTURE_NONE,
|
2013-01-29 08:18:06 +00:00
|
|
|
effects->xrenderBufferPicture(), 0, 0, 0, 0, x, y, FPS_WIDTH, MAX_TIME);
|
|
|
|
|
2007-09-06 15:02:59 +00:00
|
|
|
|
|
|
|
// Paint FPS graph
|
2011-01-30 14:34:42 +00:00
|
|
|
paintFPSGraph(x + FPS_WIDTH, y);
|
2007-09-06 15:02:59 +00:00
|
|
|
|
|
|
|
// Paint amount of rendered pixels graph
|
2011-01-30 14:34:42 +00:00
|
|
|
paintDrawSizeGraph(x + FPS_WIDTH + MAX_TIME, y);
|
2013-08-04 12:50:38 +00:00
|
|
|
|
|
|
|
// Paint FPS numerical value
|
|
|
|
if (fpsTextRect.isValid()) {
|
|
|
|
QImage textImg(fpsTextImage(fps));
|
|
|
|
XRenderPicture textPic(textImg);
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_render_composite(xcbConnection(), XCB_RENDER_PICT_OP_OVER, textPic, XCB_RENDER_PICTURE_NONE,
|
2013-08-04 12:50:38 +00:00
|
|
|
effects->xrenderBufferPicture(), 0, 0, 0, 0, fpsTextRect.x(), fpsTextRect.y(), textImg.width(), textImg.height());
|
|
|
|
effects->addRepaint(fpsTextRect);
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-06-06 11:07:15 +00:00
|
|
|
#endif
|
2007-09-06 15:02:59 +00:00
|
|
|
|
2013-06-21 12:17:32 +00:00
|
|
|
void ShowFpsEffect::paintQPainter(int fps)
|
|
|
|
{
|
|
|
|
QPainter *painter = effects->scenePainter();
|
|
|
|
painter->save();
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2007-09-06 15:02:59 +00:00
|
|
|
void ShowFpsEffect::paintFPSGraph(int x, int y)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-09-06 15:02:59 +00:00
|
|
|
// Paint FPS graph
|
|
|
|
QList<int> lines;
|
|
|
|
lines << 10 << 20 << 50;
|
|
|
|
QList<int> values;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0;
|
|
|
|
i < NUM_PAINTS;
|
|
|
|
++i) {
|
|
|
|
values.append(paints[(i + paints_pos) % NUM_PAINTS ]);
|
2007-09-06 15:02:59 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
paintGraph(x, y, values, lines, true);
|
|
|
|
}
|
2007-09-06 15:02:59 +00:00
|
|
|
|
|
|
|
void ShowFpsEffect::paintDrawSizeGraph(int x, int y)
|
|
|
|
{
|
|
|
|
int max_drawsize = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0; i < NUM_PAINTS; i++)
|
|
|
|
max_drawsize = qMax(max_drawsize, paint_size[ i ]);
|
2007-09-06 15:02:59 +00:00
|
|
|
|
2007-09-06 15:30:57 +00:00
|
|
|
// 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);
|
2007-09-06 15:02:59 +00:00
|
|
|
QList<int> drawlines;
|
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int logh = (int)min_pixels_log; logh <= max_pixels_log; logh++)
|
|
|
|
drawlines.append((int)((logh - min_pixels_log) * drawscale) + minh);
|
2007-09-06 15:02:59 +00:00
|
|
|
|
|
|
|
QList<int> drawvalues;
|
2011-01-30 14:34:42 +00:00
|
|
|
for (int i = 0;
|
|
|
|
i < NUM_PAINTS;
|
|
|
|
++i) {
|
|
|
|
int value = paint_size[(i + paints_pos) % NUM_PAINTS ];
|
2007-09-06 15:30:57 +00:00
|
|
|
int h = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
if (value > 0) {
|
|
|
|
h = (int)((log10((double)value) - min_pixels_log) * drawscale);
|
|
|
|
h = qMin(qMax(0, h) + minh, MAX_TIME);
|
2007-09-06 15:02:59 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
drawvalues.append(h);
|
2007-09-06 15:02:59 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
paintGraph(x, y, drawvalues, drawlines, false);
|
|
|
|
}
|
2007-09-06 15:02:59 +00:00
|
|
|
|
2011-01-30 14:34:42 +00:00
|
|
|
void ShowFpsEffect::paintGraph(int x, int y, QList<int> values, QList<int> lines, bool colorize)
|
|
|
|
{
|
2012-09-20 09:33:32 +00:00
|
|
|
if (effects->isOpenGLCompositing()) {
|
2011-01-06 10:58:03 +00:00
|
|
|
QColor color(0, 0, 0);
|
|
|
|
color.setAlphaF(alpha);
|
|
|
|
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
|
|
|
|
vbo->reset();
|
|
|
|
vbo->setColor(color);
|
|
|
|
QVector<float> verts;
|
2007-09-06 15:02:59 +00:00
|
|
|
// First draw the lines
|
2011-01-30 14:34:42 +00:00
|
|
|
foreach (int h, lines) {
|
2011-01-06 10:58:03 +00:00
|
|
|
verts << x << y - h;
|
|
|
|
verts << x + values.count() << y - h;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
|
|
|
vbo->setData(verts.size() / 2, 2, verts.constData(), NULL);
|
2011-01-06 10:58:03 +00:00
|
|
|
vbo->render(GL_LINES);
|
2007-09-06 15:02:59 +00:00
|
|
|
// Then the graph values
|
2011-01-06 10:58:03 +00:00
|
|
|
int lastValue = 0;
|
|
|
|
verts.clear();
|
|
|
|
for (int i = 0; i < values.count(); i++) {
|
2007-09-06 15:02:59 +00:00
|
|
|
int value = values[ i ];
|
2011-01-06 10:58:03 +00:00
|
|
|
if (colorize && value != lastValue) {
|
|
|
|
if (!verts.isEmpty()) {
|
2011-01-30 14:34:42 +00:00
|
|
|
vbo->setData(verts.size() / 2, 2, verts.constData(), NULL);
|
2011-01-06 10:58:03 +00:00
|
|
|
vbo->render(GL_LINES);
|
|
|
|
}
|
|
|
|
verts.clear();
|
|
|
|
if (value <= 10) {
|
|
|
|
color = QColor(0, 255, 0);
|
|
|
|
} else if (value <= 20) {
|
2011-01-30 14:34:42 +00:00
|
|
|
color = QColor(255, 255, 0);
|
|
|
|
} else if (value <= 50) {
|
2011-01-06 10:58:03 +00:00
|
|
|
color = QColor(255, 0, 0);
|
|
|
|
} else {
|
|
|
|
color = QColor(0, 0, 0);
|
2007-09-06 15:02:59 +00:00
|
|
|
}
|
2011-01-06 10:58:03 +00:00
|
|
|
vbo->setColor(color);
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-06 10:58:03 +00:00
|
|
|
verts << x + values.count() - i << y;
|
|
|
|
verts << x + values.count() - i << y - value;
|
|
|
|
lastValue = value;
|
|
|
|
}
|
|
|
|
if (!verts.isEmpty()) {
|
2011-01-30 14:34:42 +00:00
|
|
|
vbo->setData(verts.size() / 2, 2, verts.constData(), NULL);
|
2011-01-06 10:58:03 +00:00
|
|
|
vbo->render(GL_LINES);
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-12-17 14:14:53 +00:00
|
|
|
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
2011-01-30 14:34:42 +00:00
|
|
|
if (effects->compositingType() == XRenderCompositing) {
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_pixmap_t pixmap = xcb_generate_id(xcbConnection());
|
|
|
|
xcb_create_pixmap(xcbConnection(), 32, pixmap, x11RootWindow(), values.count(), MAX_TIME);
|
2011-01-30 14:34:42 +00:00
|
|
|
XRenderPicture p(pixmap, 32);
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_free_pixmap(xcbConnection(), pixmap);
|
2013-01-29 08:18:06 +00:00
|
|
|
xcb_render_color_t col;
|
2011-01-30 14:34:42 +00:00
|
|
|
col.alpha = int(alpha * 0xffff);
|
2007-09-06 15:02:59 +00:00
|
|
|
|
|
|
|
// Draw background
|
2011-01-30 14:34:42 +00:00
|
|
|
col.red = col.green = col.blue = int(alpha * 0xffff); // white
|
2013-01-29 08:18:06 +00:00
|
|
|
xcb_rectangle_t rect = {0, 0, uint16_t(values.count()), uint16_t(MAX_TIME)};
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_render_fill_rectangles(xcbConnection(), XCB_RENDER_PICT_OP_SRC, p, col, 1, &rect);
|
2007-09-06 15:02:59 +00:00
|
|
|
|
|
|
|
// Then the values
|
2011-01-30 14:34:42 +00:00
|
|
|
col.red = col.green = col.blue = int(alpha * 0x8000); // grey
|
|
|
|
for (int i = 0; i < values.count(); i++) {
|
2007-09-06 15:02:59 +00:00
|
|
|
int value = values[ i ];
|
2011-01-30 14:34:42 +00:00
|
|
|
if (colorize) {
|
|
|
|
if (value <= 10) {
|
|
|
|
// green
|
2007-09-06 15:02:59 +00:00
|
|
|
col.red = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
col.green = int(alpha * 0xffff);
|
2007-09-06 15:02:59 +00:00
|
|
|
col.blue = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
} else if (value <= 20) {
|
|
|
|
// yellow
|
|
|
|
col.red = int(alpha * 0xffff);
|
|
|
|
col.green = int(alpha * 0xffff);
|
2007-09-06 15:02:59 +00:00
|
|
|
col.blue = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
} else if (value <= 50) {
|
|
|
|
// red
|
|
|
|
col.red = int(alpha * 0xffff);
|
2007-09-06 15:02:59 +00:00
|
|
|
col.green = 0;
|
|
|
|
col.blue = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
} else {
|
|
|
|
// black
|
2007-09-06 15:02:59 +00:00
|
|
|
col.red = 0;
|
|
|
|
col.green = 0;
|
|
|
|
col.blue = 0;
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2013-01-29 08:18:06 +00:00
|
|
|
xcb_rectangle_t rect = {int16_t(values.count() - i), int16_t(MAX_TIME - value), 1, uint16_t(value)};
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_render_fill_rectangles(xcbConnection(), XCB_RENDER_PICT_OP_SRC, p, col, 1, &rect);
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-09-06 15:10:03 +00:00
|
|
|
|
|
|
|
// Then the lines
|
|
|
|
col.red = col.green = col.blue = 0; // black
|
2013-01-29 08:18:06 +00:00
|
|
|
QVector<xcb_rectangle_t> rects;
|
|
|
|
foreach (int h, lines) {
|
|
|
|
xcb_rectangle_t rect = {0, int16_t(MAX_TIME - h), uint16_t(values.count()), 1};
|
|
|
|
rects << rect;
|
|
|
|
}
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_render_fill_rectangles(xcbConnection(), XCB_RENDER_PICT_OP_SRC, p, col, rects.count(), rects.constData());
|
2007-09-06 15:10:03 +00:00
|
|
|
|
|
|
|
// Finally render the pixmap onto screen
|
2014-04-16 13:58:06 +00:00
|
|
|
xcb_render_composite(xcbConnection(), alpha != 1.0 ? XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_SRC, p,
|
2013-01-29 08:18:06 +00:00
|
|
|
XCB_RENDER_PICTURE_NONE, effects->xrenderBufferPicture(), 0, 0, 0, 0, x, y, values.count(), MAX_TIME);
|
2007-04-29 17:35:43 +00:00
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
#endif
|
2013-06-21 12:17:32 +00:00
|
|
|
if (effects->compositingType() == QPainterCompositing) {
|
|
|
|
QPainter *painter = effects->scenePainter();
|
|
|
|
painter->setPen(Qt::black);
|
|
|
|
// First draw the lines
|
|
|
|
foreach (int h, 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);
|
|
|
|
}
|
|
|
|
}
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
|
|
|
void ShowFpsEffect::postPaintScreen()
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2007-04-29 17:35:43 +00:00
|
|
|
effects->postPaintScreen();
|
|
|
|
paints[ paints_pos ] = t.elapsed();
|
2011-01-30 14:34:42 +00:00
|
|
|
if (++paints_pos == NUM_PAINTS)
|
2007-04-29 17:35:43 +00:00
|
|
|
paints_pos = 0;
|
2011-01-30 14:34:42 +00:00
|
|
|
effects->addRepaint(fps_rect);
|
|
|
|
}
|
2007-04-29 17:35:43 +00:00
|
|
|
|
2013-08-04 12:50:38 +00:00
|
|
|
QImage ShowFpsEffect::fpsTextImage(int fps)
|
2011-01-30 14:34:42 +00:00
|
|
|
{
|
2008-02-05 17:20:08 +00:00
|
|
|
QImage im(100, 100, QImage::Format_ARGB32);
|
2013-08-04 12:50:38 +00:00
|
|
|
im.fill(Qt::transparent);
|
2008-02-05 17:20:08 +00:00
|
|
|
QPainter painter(&im);
|
|
|
|
painter.setFont(textFont);
|
|
|
|
painter.setPen(textColor);
|
|
|
|
painter.drawText(QRect(0, 0, 100, 100), textAlign, QString::number(fps));
|
2013-08-04 12:50:38 +00:00
|
|
|
painter.end();
|
|
|
|
return im;
|
2011-01-30 14:34:42 +00:00
|
|
|
}
|
2008-02-05 17:20:08 +00:00
|
|
|
|
2007-04-29 17:35:43 +00:00
|
|
|
} // namespace
|