[wayland] Add a virtual framebuffer backend
A new backend which doesn't present the rendered output. It uses a QPainter scene, renders to a QImage but doesn't present it anywhere. Thus a real virtual backend. By exporting the environment variable KWIN_WAYLAND_VIRTUAL_SCREENSHOTS the backend creates a temporary dir, prints the path to std-out and saves each rendered frame into that directory. Of course with exit it will be deleted again.
This commit is contained in:
parent
007a317099
commit
bfa9646d1d
10 changed files with 427 additions and 1 deletions
|
@ -5,6 +5,7 @@ add_subdirectory(fbdev)
|
|||
if(HAVE_LIBHYBRIS)
|
||||
add_subdirectory(hwcomposer)
|
||||
endif()
|
||||
add_subdirectory(virtual)
|
||||
add_subdirectory(wayland)
|
||||
if(X11_XCB_FOUND)
|
||||
add_subdirectory(x11)
|
||||
|
|
15
backends/virtual/CMakeLists.txt
Normal file
15
backends/virtual/CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
set(VIRTUAL_SOURCES
|
||||
virtual_backend.cpp
|
||||
scene_qpainter_virtual_backend.cpp
|
||||
screens_virtual.cpp
|
||||
)
|
||||
|
||||
add_library(KWinWaylandVirtualBackend MODULE ${VIRTUAL_SOURCES})
|
||||
target_link_libraries(KWinWaylandVirtualBackend kwin)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
KWinWaylandVirtualBackend
|
||||
DESTINATION
|
||||
${PLUGIN_INSTALL_DIR}/org.kde.kwin.waylandbackends/
|
||||
)
|
99
backends/virtual/scene_qpainter_virtual_backend.cpp
Normal file
99
backends/virtual/scene_qpainter_virtual_backend.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#include "scene_qpainter_virtual_backend.h"
|
||||
#include "virtual_backend.h"
|
||||
#include "cursor.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
VirtualQPainterBackend::VirtualQPainterBackend(VirtualBackend *backend)
|
||||
: QPainterBackend()
|
||||
, m_backBuffer(backend->size(), QImage::Format_RGB32)
|
||||
, m_backend(backend)
|
||||
{
|
||||
if (qEnvironmentVariableIsSet("KWIN_WAYLAND_VIRTUAL_SCREENSHOTS")) {
|
||||
m_screenshotDir.reset(new QTemporaryDir);
|
||||
if (!m_screenshotDir->isValid()) {
|
||||
m_screenshotDir.reset();
|
||||
}
|
||||
if (!m_screenshotDir.isNull()) {
|
||||
qDebug() << "Screenshots saved to: " << m_screenshotDir->path();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VirtualQPainterBackend::~VirtualQPainterBackend() = default;
|
||||
|
||||
QImage *VirtualQPainterBackend::buffer()
|
||||
{
|
||||
return &m_backBuffer;
|
||||
}
|
||||
|
||||
bool VirtualQPainterBackend::needsFullRepaint() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void VirtualQPainterBackend::prepareRenderingFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void VirtualQPainterBackend::screenGeometryChanged(const QSize &size)
|
||||
{
|
||||
if (m_backBuffer.size() != size) {
|
||||
m_backBuffer = QImage(size, QImage::Format_RGB32);
|
||||
m_backBuffer.fill(Qt::black);
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualQPainterBackend::present(int mask, const QRegion &damage)
|
||||
{
|
||||
Q_UNUSED(mask)
|
||||
Q_UNUSED(damage)
|
||||
if (!m_screenshotDir.isNull()) {
|
||||
m_backBuffer.save(QStringLiteral("%1/%2.png").arg(m_screenshotDir->path()).arg(QString::number(m_frameCounter++)));
|
||||
}
|
||||
}
|
||||
|
||||
bool VirtualQPainterBackend::usesOverlayWindow() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void VirtualQPainterBackend::renderCursor(QPainter *painter)
|
||||
{
|
||||
if (!m_backend->usesSoftwareCursor()) {
|
||||
return;
|
||||
}
|
||||
const QImage img = m_backend->softwareCursor();
|
||||
if (img.isNull()) {
|
||||
return;
|
||||
}
|
||||
const QPoint cursorPos = Cursor::pos();
|
||||
const QPoint hotspot = m_backend->softwareCursorHotspot();
|
||||
painter->drawImage(cursorPos - hotspot, img);
|
||||
m_backend->markCursorAsRendered();
|
||||
}
|
||||
|
||||
}
|
58
backends/virtual/scene_qpainter_virtual_backend.h
Normal file
58
backends/virtual/scene_qpainter_virtual_backend.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_SCENE_QPAINTER_X11_BACKEND_H
|
||||
#define KWIN_SCENE_QPAINTER_X11_BACKEND_H
|
||||
|
||||
#include "scene_qpainter.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QTemporaryDir;
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class VirtualBackend;
|
||||
|
||||
class VirtualQPainterBackend : public QObject, public QPainterBackend
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VirtualQPainterBackend(VirtualBackend *backend);
|
||||
virtual ~VirtualQPainterBackend();
|
||||
|
||||
QImage *buffer() override;
|
||||
bool needsFullRepaint() const override;
|
||||
bool usesOverlayWindow() const override;
|
||||
void prepareRenderingFrame() override;
|
||||
void present(int mask, const QRegion &damage) override;
|
||||
void screenGeometryChanged(const QSize &size) override;
|
||||
void renderCursor(QPainter *painter) override;
|
||||
|
||||
private:
|
||||
QImage m_backBuffer;
|
||||
VirtualBackend *m_backend;
|
||||
QScopedPointer<QTemporaryDir> m_screenshotDir;
|
||||
int m_frameCounter = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
70
backends/virtual/screens_virtual.cpp
Normal file
70
backends/virtual/screens_virtual.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#include "screens_virtual.h"
|
||||
#include "virtual_backend.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
VirtualScreens::VirtualScreens(VirtualBackend *backend, QObject *parent)
|
||||
: Screens(parent)
|
||||
, m_backend(backend)
|
||||
{
|
||||
}
|
||||
|
||||
VirtualScreens::~VirtualScreens() = default;
|
||||
|
||||
void VirtualScreens::init()
|
||||
{
|
||||
KWin::Screens::init();
|
||||
connect(m_backend, &VirtualBackend::sizeChanged,
|
||||
this, &VirtualScreens::startChangedTimer);
|
||||
updateCount();
|
||||
emit changed();
|
||||
}
|
||||
|
||||
QRect VirtualScreens::geometry(int screen) const
|
||||
{
|
||||
if (screen == 0) {
|
||||
return QRect(QPoint(0, 0), size(screen));
|
||||
}
|
||||
return QRect();
|
||||
}
|
||||
|
||||
QSize VirtualScreens::size(int screen) const
|
||||
{
|
||||
if (screen == 0) {
|
||||
return m_backend->size();
|
||||
}
|
||||
return QSize();
|
||||
}
|
||||
|
||||
void VirtualScreens::updateCount()
|
||||
{
|
||||
setCount(1);
|
||||
}
|
||||
|
||||
int VirtualScreens::number(const QPoint &pos) const
|
||||
{
|
||||
Q_UNUSED(pos)
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
47
backends/virtual/screens_virtual.h
Normal file
47
backends/virtual/screens_virtual.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_SCREENS_VIRTUAL_H
|
||||
#define KWIN_SCREENS_VIRTUAL_H
|
||||
#include "screens.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
class VirtualBackend;
|
||||
|
||||
class VirtualScreens : public Screens
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VirtualScreens(VirtualBackend *backend, QObject *parent = nullptr);
|
||||
virtual ~VirtualScreens();
|
||||
void init() override;
|
||||
QRect geometry(int screen) const override;
|
||||
int number(const QPoint &pos) const override;
|
||||
QSize size(int screen) const override;
|
||||
void updateCount() override;
|
||||
|
||||
private:
|
||||
VirtualBackend *m_backend;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
8
backends/virtual/virtual.json
Normal file
8
backends/virtual/virtual.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"KPlugin": {
|
||||
"Id": "KWinWaylandVirtualBackend",
|
||||
"Name": "virtual",
|
||||
"Description": "Render to a virtual framebuffer."
|
||||
},
|
||||
"input": true
|
||||
}
|
61
backends/virtual/virtual_backend.cpp
Normal file
61
backends/virtual/virtual_backend.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#include "virtual_backend.h"
|
||||
#include "scene_qpainter_virtual_backend.h"
|
||||
#include "screens_virtual.h"
|
||||
#include "wayland_server.h"
|
||||
// KWayland
|
||||
#include <KWayland/Server/seat_interface.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
VirtualBackend::VirtualBackend(QObject *parent)
|
||||
: AbstractBackend(parent)
|
||||
{
|
||||
setSoftWareCursor(true);
|
||||
setSupportsPointerWarping(true);
|
||||
// currently only QPainter - enforce it
|
||||
qputenv("KWIN_COMPOSE", QByteArrayLiteral("Q"));
|
||||
}
|
||||
|
||||
VirtualBackend::~VirtualBackend() = default;
|
||||
|
||||
void VirtualBackend::init()
|
||||
{
|
||||
m_size = initialWindowSize();
|
||||
setReady(true);
|
||||
waylandServer()->seat()->setHasPointer(true);
|
||||
waylandServer()->seat()->setHasKeyboard(true);
|
||||
waylandServer()->seat()->setHasTouch(true);
|
||||
emit screensQueried();
|
||||
}
|
||||
|
||||
Screens *VirtualBackend::createScreens(QObject *parent)
|
||||
{
|
||||
return new VirtualScreens(this, parent);
|
||||
}
|
||||
|
||||
QPainterBackend *VirtualBackend::createQPainterBackend()
|
||||
{
|
||||
return new VirtualQPainterBackend(this);
|
||||
}
|
||||
|
||||
}
|
59
backends/virtual/virtual_backend.h
Normal file
59
backends/virtual/virtual_backend.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
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/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_X11WINDOWED_BACKEND_H
|
||||
#define KWIN_X11WINDOWED_BACKEND_H
|
||||
#include "abstract_backend.h"
|
||||
|
||||
#include <kwin_export.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QSize>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class KWIN_EXPORT VirtualBackend : public AbstractBackend
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(KWin::AbstractBackend)
|
||||
Q_PLUGIN_METADATA(IID "org.kde.kwin.AbstractBackend" FILE "virtual.json")
|
||||
Q_PROPERTY(QSize size READ size NOTIFY sizeChanged)
|
||||
public:
|
||||
VirtualBackend(QObject *parent = nullptr);
|
||||
virtual ~VirtualBackend();
|
||||
void init() override;
|
||||
|
||||
QSize size() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
Screens *createScreens(QObject *parent = nullptr) override;
|
||||
QPainterBackend* createQPainterBackend() override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void sizeChanged();
|
||||
|
||||
private:
|
||||
QSize m_size;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -326,6 +326,7 @@ static const QString s_drmPlugin = QStringLiteral("KWinWaylandDrmBackend");
|
|||
#if HAVE_LIBHYBRIS
|
||||
static const QString s_hwcomposerPlugin = QStringLiteral("KWinWaylandHwcomposerBackend");
|
||||
#endif
|
||||
static const QString s_virtualPlugin = QStringLiteral("KWinWaylandVirtualBackend");
|
||||
|
||||
static QString automaticBackendSelection()
|
||||
{
|
||||
|
@ -411,6 +412,7 @@ int main(int argc, char * argv[])
|
|||
QCommandLineOption waylandDisplayOption(QStringLiteral("wayland-display"),
|
||||
i18n("The Wayland Display to use in windowed mode on platform Wayland."),
|
||||
QStringLiteral("display"));
|
||||
QCommandLineOption virtualFbOption(QStringLiteral("virtual"), i18n("Render to a virtual framebuffer."));
|
||||
QCommandLineOption widthOption(QStringLiteral("width"),
|
||||
i18n("The width for windowed mode. Default width is 1024."),
|
||||
QStringLiteral("width"));
|
||||
|
@ -437,7 +439,10 @@ int main(int argc, char * argv[])
|
|||
parser.addOption(framebufferOption);
|
||||
parser.addOption(framebufferDeviceOption);
|
||||
}
|
||||
if (hasPlugin(KWin::s_x11Plugin)) {
|
||||
if (hasPlugin(KWin::s_virtualPlugin)) {
|
||||
parser.addOption(virtualFbOption);
|
||||
}
|
||||
if (hasPlugin(KWin::s_x11Plugin) || hasPlugin(KWin::s_virtualPlugin)) {
|
||||
parser.addOption(widthOption);
|
||||
parser.addOption(heightOption);
|
||||
}
|
||||
|
@ -545,6 +550,9 @@ int main(int argc, char * argv[])
|
|||
pluginName = KWin::s_hwcomposerPlugin;
|
||||
}
|
||||
#endif
|
||||
if (parser.isSet(virtualFbOption)) {
|
||||
pluginName = KWin::s_virtualPlugin;
|
||||
}
|
||||
|
||||
if (pluginName.isEmpty()) {
|
||||
std::cerr << "No backend specified through command line argument, trying auto resolution" << std::endl;
|
||||
|
|
Loading…
Reference in a new issue