Move QPainter compositor into plugin

This change is similar to D7232 and moves the scene_qpainter into a
dedicated plugin. Compared to the XRender case it's more complicated as
the platform plugins need to implement a platform specific backend.

The base implementation for this part used to be in scene_qpainter. As
the idea is to completly move it away from KWin core it would be point
less to still have the backend definition in KWin core, but it cannot
be in the scene plugin as otherwise all platforms need to link the
plugin.

To solve this a new platformsupport subdirectory is added which contains
the scene platform backend as a static library. For the OpenGL scene such
a static library will also be required.

Test Plan: SceneQPainter test still passes, nested compositor still works

Reviewers: #kwin, #plasma

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D7259
This commit is contained in:
Martin Flöser 2017-08-11 21:40:49 +02:00
parent c398db3c45
commit 535b107969
23 changed files with 272 additions and 134 deletions

View file

@ -347,6 +347,7 @@ include_directories(BEFORE
${CMAKE_CURRENT_SOURCE_DIR}/libkwineffects
${CMAKE_CURRENT_SOURCE_DIR}/effects
${CMAKE_CURRENT_SOURCE_DIR}/tabbox
${CMAKE_CURRENT_SOURCE_DIR}/platformsupport
)
add_subdirectory( libkwineffects )
@ -410,7 +411,6 @@ set(kwin_KDEINIT_SRCS
unmanaged.cpp
scene.cpp
scene_opengl.cpp
scene_qpainter.cpp
screenlockerwatcher.cpp
thumbnailitem.cpp
lanczosfilter.cpp
@ -625,6 +625,7 @@ target_link_libraries(kwin_wayland kwin)
install(TARGETS kwin_wayland ${INSTALL_TARGETS_DEFAULT_ARGS} )
add_subdirectory(platformsupport)
add_subdirectory(plugins)
########### install files ###############

View file

@ -31,7 +31,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "overlaywindow.h"
#include "scene.h"
#include "scene_opengl.h"
#include "scene_qpainter.h"
#include "screens.h"
#include "shadow.h"
#include "useractions.h"
@ -249,10 +248,6 @@ void Compositor::slotCompositingOptionsInitialized()
// Do not Fall back to XRender - it causes problems when selfcheck fails during startup, but works later on
break;
}
case QPainterCompositing:
qCDebug(KWIN_CORE) << "Initializing QPainter compositing";
m_scene = SceneQPainter::createScene(this);
break;
default:
qCDebug(KWIN_CORE) << "No compositing enabled";
m_starting = false;

View file

@ -17,3 +17,4 @@ aurorae KWin Aurorae Window Decoration Engine
kwin_xkbcommon KWin xkbcommon integration
kwin_qpa_plugin KWin QtPlatformAbstraction plugin
kwin_scene_xrender KWin XRender based compositor scene plugin
kwin_scene_qpainter KWin QPainter based compositor scene plugin

View file

@ -0,0 +1 @@
add_subdirectory(scenes)

View file

@ -0,0 +1 @@
add_subdirectory(qpainter)

View file

@ -0,0 +1,16 @@
set(SCENE_QPAINTER_BACKEND_SRCS backend.cpp)
include(ECMQtDeclareLoggingCategory)
ecm_qt_declare_logging_category(SCENE_QPAINTER_BACKEND_SRCS
HEADER
logging.h
IDENTIFIER
KWIN_QPAINTER
CATEGORY_NAME
kwin_scene_qpainter
DEFAULT_SEVERITY
Critical
)
add_library(SceneQPainterBackend STATIC ${SCENE_QPAINTER_BACKEND_SRCS})
target_link_libraries(SceneQPainterBackend Qt5::Core)

View file

@ -0,0 +1,68 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2013 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 "backend.h"
#include <logging.h>
#include <QtGlobal>
namespace KWin
{
QPainterBackend::QPainterBackend()
: m_failed(false)
{
}
QPainterBackend::~QPainterBackend()
{
}
OverlayWindow* QPainterBackend::overlayWindow()
{
return nullptr;
}
void QPainterBackend::showOverlay()
{
}
void QPainterBackend::screenGeometryChanged(const QSize &size)
{
Q_UNUSED(size)
}
void QPainterBackend::setFailed(const QString &reason)
{
qCWarning(KWIN_QPAINTER) << "Creating the QPainter backend failed: " << reason;
m_failed = true;
}
bool QPainterBackend::perScreenRendering() const
{
return false;
}
QImage *QPainterBackend::bufferForScreen(int screenId)
{
Q_UNUSED(screenId)
return buffer();
}
}

View file

@ -0,0 +1,108 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2013 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_BACKEND_H
#define KWIN_SCENE_QPAINTER_BACKEND_H
class QImage;
class QRegion;
class QSize;
class QString;
namespace KWin {
class OverlayWindow;
class QPainterBackend
{
public:
virtual ~QPainterBackend();
virtual void present(int mask, const QRegion &damage) = 0;
/**
* @brief Returns the OverlayWindow used by the backend.
*
* A backend does not have to use an OverlayWindow, this is mostly for the X world.
* In case the backend does not use an OverlayWindow it is allowed to return @c null.
* It's the task of the caller to check whether it is @c null.
*
* @return :OverlayWindow*
**/
virtual OverlayWindow *overlayWindow();
virtual bool usesOverlayWindow() const = 0;
virtual void prepareRenderingFrame() = 0;
/**
* @brief Shows the Overlay Window
*
* Default implementation does nothing.
*/
virtual void showOverlay();
/**
* @brief React on screen geometry changes.
*
* Default implementation does nothing. Override if specific functionality is required.
*
* @param size The new screen size
*/
virtual void screenGeometryChanged(const QSize &size);
/**
* @brief Whether the creation of the Backend failed.
*
* The SceneQPainter should test whether the Backend got constructed correctly. If this method
* returns @c true, the SceneQPainter should not try to start the rendering.
*
* @return bool @c true if the creation of the Backend failed, @c false otherwise.
**/
bool isFailed() const {
return m_failed;
}
virtual QImage *buffer() = 0;
/**
* Overload for the case that there is a different buffer per screen.
* Default implementation just calls buffer.
* @param screenId The id of the screen as used in Screens
* @todo Get a better identifier for screen then a counter variable
**/
virtual QImage *bufferForScreen(int screenId);
virtual bool needsFullRepaint() const = 0;
/**
* Whether the rendering needs to be split per screen.
* Default implementation returns @c false.
**/
virtual bool perScreenRendering() const;
protected:
QPainterBackend();
/**
* @brief Sets the backend initialization to failed.
*
* This method should be called by the concrete subclass in case the initialization failed.
* The given @p reason is logged as a warning.
*
* @param reason The reason why the initialization failed.
**/
void setFailed(const QString &reason);
private:
bool m_failed;
};
} // KWin
#endif

View file

@ -17,7 +17,7 @@ if(HAVE_GBM)
endif()
add_library(KWinWaylandDrmBackend MODULE ${DRM_SOURCES})
target_link_libraries(KWinWaylandDrmBackend kwin Libdrm::Libdrm)
target_link_libraries(KWinWaylandDrmBackend kwin Libdrm::Libdrm SceneQPainterBackend)
if(HAVE_GBM)
target_link_libraries(KWinWaylandDrmBackend gbm::gbm)

View file

@ -19,8 +19,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_SCENE_QPAINTER_DRM_BACKEND_H
#define KWIN_SCENE_QPAINTER_DRM_BACKEND_H
#include "scene_qpainter.h"
#include <platformsupport/scenes/qpainter/backend.h>
#include <QObject>
#include <QVector>
namespace KWin
{

View file

@ -5,7 +5,7 @@ set(FBDEV_SOURCES
)
add_library(KWinWaylandFbdevBackend MODULE ${FBDEV_SOURCES})
target_link_libraries(KWinWaylandFbdevBackend kwin)
target_link_libraries(KWinWaylandFbdevBackend kwin SceneQPainterBackend)
install(
TARGETS

View file

@ -19,9 +19,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_SCENE_QPAINTER_FB_BACKEND_H
#define KWIN_SCENE_QPAINTER_FB_BACKEND_H
#include "scene_qpainter.h"
#include <platformsupport/scenes/qpainter/backend.h>
#include <QObject>
#include <QImage>
namespace KWin
{

View file

@ -9,7 +9,7 @@ include(ECMQtDeclareLoggingCategory)
ecm_qt_declare_logging_category(VIRTUAL_SOURCES HEADER logging.h IDENTIFIER KWIN_VIRTUAL CATEGORY_NAME kwin_platform_virtual DEFAULT_SEVERITY Critical)
add_library(KWinWaylandVirtualBackend MODULE ${VIRTUAL_SOURCES})
target_link_libraries(KWinWaylandVirtualBackend kwin)
target_link_libraries(KWinWaylandVirtualBackend kwin SceneQPainterBackend)
if(HAVE_GBM)
target_link_libraries(KWinWaylandVirtualBackend gbm::gbm)

View file

@ -20,9 +20,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KWIN_SCENE_QPAINTER_VIRTUAL_BACKEND_H
#define KWIN_SCENE_QPAINTER_VIRTUAL_BACKEND_H
#include "scene_qpainter.h"
#include <platformsupport/scenes/qpainter/backend.h>
#include <QObject>
#include <QVector>
namespace KWin
{

View file

@ -9,7 +9,7 @@ if(HAVE_WAYLAND_EGL)
endif()
add_library(KWinWaylandWaylandBackend MODULE ${WAYLAND_BACKEND_SOURCES})
target_link_libraries(KWinWaylandWaylandBackend kwin KF5::WaylandClient)
target_link_libraries(KWinWaylandWaylandBackend kwin KF5::WaylandClient SceneQPainterBackend)
if(HAVE_WAYLAND_EGL)
target_link_libraries(KWinWaylandWaylandBackend Wayland::Egl)

View file

@ -20,9 +20,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KWIN_SCENE_QPAINTER_WAYLAND_BACKEND_H
#define KWIN_SCENE_QPAINTER_WAYLAND_BACKEND_H
#include "scene_qpainter.h"
#include <platformsupport/scenes/qpainter/backend.h>
#include <QObject>
#include <QImage>
#include <QWeakPointer>
namespace KWayland
{

View file

@ -6,7 +6,7 @@ set(X11BACKEND_SOURCES
)
add_library(KWinWaylandX11Backend MODULE ${X11BACKEND_SOURCES})
target_link_libraries(KWinWaylandX11Backend eglx11common kwin X11::XCB)
target_link_libraries(KWinWaylandX11Backend eglx11common kwin X11::XCB SceneQPainterBackend)
install(
TARGETS

View file

@ -20,9 +20,13 @@ 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 <platformsupport/scenes/qpainter/backend.h>
#include <QObject>
#include <QImage>
#include <QVector>
#include <xcb/xcb.h>
namespace KWin
{

View file

@ -1,3 +1,4 @@
add_subdirectory(qpainter)
if( KWIN_BUILD_XRENDER_COMPOSITING )
add_subdirectory(xrender)
endif()

View file

@ -0,0 +1,14 @@
set(SCENE_QPAINTER_SRCS scene_qpainter.cpp)
add_library(KWinSceneQPainter MODULE scene_qpainter.cpp)
target_link_libraries(KWinSceneQPainter
kwin
SceneQPainterBackend
)
install(
TARGETS
KWinSceneQPainter
DESTINATION
${PLUGIN_INSTALL_DIR}/org.kde.kwin.scenes/
)

View file

@ -0,0 +1,9 @@
{
"KPlugin": {
"Description": "KWin Compositor plugin rendering through QPainter",
"Id": "KWinSceneQPainter",
"Name": "SceneQPainter"
},
"CompositingType": 4
}

View file

@ -41,49 +41,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
namespace KWin
{
//****************************************
// QPainterBackend
//****************************************
QPainterBackend::QPainterBackend()
: m_failed(false)
{
}
QPainterBackend::~QPainterBackend()
{
}
OverlayWindow* QPainterBackend::overlayWindow()
{
return NULL;
}
void QPainterBackend::showOverlay()
{
}
void QPainterBackend::screenGeometryChanged(const QSize &size)
{
Q_UNUSED(size)
}
void QPainterBackend::setFailed(const QString &reason)
{
qCWarning(KWIN_CORE) << "Creating the XRender backend failed: " << reason;
m_failed = true;
}
bool QPainterBackend::perScreenRendering() const
{
return false;
}
QImage *QPainterBackend::bufferForScreen(int screenId)
{
Q_UNUSED(screenId)
return buffer();
}
//****************************************
// SceneQPainter
//****************************************
@ -688,4 +645,22 @@ void SceneQPainterDecorationRenderer::reparent(Deleted *deleted)
Renderer::reparent(deleted);
}
QPainterFactory::QPainterFactory(QObject *parent)
: SceneFactory(parent)
{
}
QPainterFactory::~QPainterFactory() = default;
Scene *QPainterFactory::create(QObject *parent) const
{
auto s = SceneQPainter::createScene(parent);
if (s && s->initFailed()) {
delete s;
s = nullptr;
}
return s;
}
} // KWin

View file

@ -21,87 +21,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KWIN_SCENE_QPAINTER_H
#include "scene.h"
#include <platformsupport/scenes/qpainter/backend.h>
#include "shadow.h"
#include "decorations/decorationrenderer.h"
namespace KWin {
class KWIN_EXPORT QPainterBackend
{
public:
virtual ~QPainterBackend();
virtual void present(int mask, const QRegion &damage) = 0;
/**
* @brief Returns the OverlayWindow used by the backend.
*
* A backend does not have to use an OverlayWindow, this is mostly for the X world.
* In case the backend does not use an OverlayWindow it is allowed to return @c null.
* It's the task of the caller to check whether it is @c null.
*
* @return :OverlayWindow*
**/
virtual OverlayWindow *overlayWindow();
virtual bool usesOverlayWindow() const = 0;
virtual void prepareRenderingFrame() = 0;
/**
* @brief Shows the Overlay Window
*
* Default implementation does nothing.
*/
virtual void showOverlay();
/**
* @brief React on screen geometry changes.
*
* Default implementation does nothing. Override if specific functionality is required.
*
* @param size The new screen size
*/
virtual void screenGeometryChanged(const QSize &size);
/**
* @brief Whether the creation of the Backend failed.
*
* The SceneQPainter should test whether the Backend got constructed correctly. If this method
* returns @c true, the SceneQPainter should not try to start the rendering.
*
* @return bool @c true if the creation of the Backend failed, @c false otherwise.
**/
bool isFailed() const {
return m_failed;
}
virtual QImage *buffer() = 0;
/**
* Overload for the case that there is a different buffer per screen.
* Default implementation just calls buffer.
* @param screenId The id of the screen as used in Screens
* @todo Get a better identifier for screen then a counter variable
**/
virtual QImage *bufferForScreen(int screenId);
virtual bool needsFullRepaint() const = 0;
/**
* Whether the rendering needs to be split per screen.
* Default implementation returns @c false.
**/
virtual bool perScreenRendering() const;
protected:
QPainterBackend();
/**
* @brief Sets the backend initialization to failed.
*
* This method should be called by the concrete subclass in case the initialization failed.
* The given @p reason is logged as a warning.
*
* @param reason The reason why the initialization failed.
**/
void setFailed(const QString &reason);
private:
bool m_failed;
};
class KWIN_EXPORT SceneQPainter : public Scene
{
Q_OBJECT
@ -240,6 +166,19 @@ private:
QImage m_images[int(DecorationPart::Count)];
};
class KWIN_EXPORT QPainterFactory : public SceneFactory
{
Q_OBJECT
Q_INTERFACES(KWin::SceneFactory)
Q_PLUGIN_METADATA(IID "org.kde.kwin.Scene" FILE "qpainter.json")
public:
explicit QPainterFactory(QObject *parent = nullptr);
~QPainterFactory() override;
Scene *create(QObject *parent = nullptr) const override;
};
inline
bool SceneQPainter::usesOverlayWindow() const
{