Move SceneXRender into a plugin

Summary:
First step for loading the compositor Scenes through plugins. The general
idea is that we currently needlessly pull in all the Scenes although only
one will be used.

E.g. on X11 we pull in QPainter, although they are not compatible. On
Wayland we pull in XRender although they are not compatible.

Furthermore our current Scene creation strategy is not really fault
tolerant and can create situations where we don't get a compositor. E.g
on fbdev backend the default settings won't work as it does not support
OpenGL.

Long term I want to tackle those conceptional problems together:
we try to load all plugins supported by the current platform till we have
a scene which works. Thus on Wayland we don't end up in a situation where
we don't have a working compositor because the configuration is bad.

To make this possible the switch statement in the Scene needs to go and
needs to be replaced by a for loop iterating over all the available
scenes on the platform. If we go there it makes sense to replace it
directly with a plugin based approach.

So this is a change which tackles the problem by first introducing the
plugin loading. The xrender based scene (as it's the most simple one)
is moved into a plugin. It is first tried to find a scene plugin and only
if there is none the existing code is used.

Test Plan: Tested all scenes

Reviewers: #kwin, #plasma

Subscribers: plasma-devel, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D7232
master
Martin Flöser 7 years ago
parent 1e13deaa1d
commit 054d923411

@ -409,7 +409,6 @@ set(kwin_KDEINIT_SRCS
toplevel.cpp
unmanaged.cpp
scene.cpp
scene_xrender.cpp
scene_opengl.cpp
scene_qpainter.cpp
screenlockerwatcher.cpp

@ -30,7 +30,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "effects.h"
#include "overlaywindow.h"
#include "scene.h"
#include "scene_xrender.h"
#include "scene_opengl.h"
#include "scene_qpainter.h"
#include "screens.h"
@ -54,6 +53,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QOpenGLContext>
#include <KGlobalAccel>
#include <KLocalizedString>
#include <KPluginLoader>
#include <KPluginMetaData>
#include <KNotification>
#include <KSelectionWatcher>
@ -199,54 +200,73 @@ void Compositor::slotCompositingOptionsInitialized()
}
}
switch(options->compositingMode()) {
case OpenGLCompositing: {
qCDebug(KWIN_CORE) << "Initializing OpenGL compositing";
const auto availablePlugins = KPluginLoader::findPlugins(QStringLiteral("org.kde.kwin.scenes"));
// Some broken drivers crash on glXQuery() so to prevent constant KWin crashes:
if (kwinApp()->platform()->openGLCompositingIsBroken())
qCWarning(KWIN_CORE) << "KWin has detected that your OpenGL library is unsafe to use";
else {
kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PreInit);
const auto pluginIt = std::find_if(availablePlugins.begin(), availablePlugins.end(),
[] (const auto &plugin) {
const auto &metaData = plugin.rawData();
auto it = metaData.find(QStringLiteral("CompositingType"));
if (it != metaData.end()) {
if ((*it).toInt() == int{options->compositingMode()}) {
return true;
}
}
return false;
});
if (pluginIt != availablePlugins.end()) {
std::unique_ptr<SceneFactory> factory{qobject_cast<SceneFactory*>(pluginIt->instantiate())};
if (factory) {
m_scene = factory->create(this);
if (m_scene) {
qCDebug(KWIN_CORE) << "Instantiated compositing plugin:" << pluginIt->name();
}
}
}
if (!m_scene) {
switch(options->compositingMode()) {
case OpenGLCompositing: {
qCDebug(KWIN_CORE) << "Initializing OpenGL compositing";
m_scene = SceneOpenGL::createScene(this);
// Some broken drivers crash on glXQuery() so to prevent constant KWin crashes:
if (kwinApp()->platform()->openGLCompositingIsBroken())
qCWarning(KWIN_CORE) << "KWin has detected that your OpenGL library is unsafe to use";
else {
kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PreInit);
kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PostInit);
m_scene = SceneOpenGL::createScene(this);
if (m_scene && !m_scene->initFailed()) {
connect(static_cast<SceneOpenGL*>(m_scene), &SceneOpenGL::resetCompositing, this, &Compositor::restart);
break; // -->
kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PostInit);
if (m_scene && !m_scene->initFailed()) {
connect(static_cast<SceneOpenGL*>(m_scene), &SceneOpenGL::resetCompositing, this, &Compositor::restart);
break; // -->
}
delete m_scene;
m_scene = NULL;
}
delete m_scene;
m_scene = NULL;
}
// Do not Fall back to XRender - it causes problems when selfcheck fails during startup, but works later on
break;
}
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
case XRenderCompositing:
qCDebug(KWIN_CORE) << "Initializing XRender compositing";
m_scene = SceneXrender::createScene(this);
break;
#endif
case QPainterCompositing:
qCDebug(KWIN_CORE) << "Initializing QPainter compositing";
m_scene = SceneQPainter::createScene(this);
break;
default:
qCDebug(KWIN_CORE) << "No compositing enabled";
m_starting = false;
if (cm_selection) {
cm_selection->owning = false;
cm_selection->release();
// Do not Fall back to XRender - it causes problems when selfcheck fails during startup, but works later on
break;
}
if (kwinApp()->platform()->requiresCompositing()) {
qCCritical(KWIN_CORE) << "The used windowing system requires compositing";
qCCritical(KWIN_CORE) << "We are going to quit KWin now as it is broken";
qApp->quit();
case QPainterCompositing:
qCDebug(KWIN_CORE) << "Initializing QPainter compositing";
m_scene = SceneQPainter::createScene(this);
break;
default:
qCDebug(KWIN_CORE) << "No compositing enabled";
m_starting = false;
if (cm_selection) {
cm_selection->owning = false;
cm_selection->release();
}
if (kwinApp()->platform()->requiresCompositing()) {
qCCritical(KWIN_CORE) << "The used windowing system requires compositing";
qCCritical(KWIN_CORE) << "We are going to quit KWin now as it is broken";
qApp->quit();
}
return;
}
return;
}
if (m_scene == NULL || m_scene->initFailed()) {
qCCritical(KWIN_CORE) << "Failed to initialize compositing, compositing disabled";

@ -16,3 +16,4 @@ kwin_scripting KWin Scripting
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

@ -25,6 +25,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <xcb/xcb.h>
#include <kwin_export.h>
class QTimer;
namespace KWin
@ -37,7 +39,7 @@ namespace Decoration
class DecoratedClientImpl;
class Renderer : public QObject
class KWIN_EXPORT Renderer : public QObject
{
Q_OBJECT
public:

@ -393,7 +393,7 @@ private:
Group* group;
};
class EffectFrameImpl
class KWIN_EXPORT EffectFrameImpl
: public QObject, public EffectFrame
{
Q_OBJECT

@ -2,6 +2,7 @@ add_subdirectory(kglobalaccel)
add_subdirectory(qpa)
add_subdirectory(idletime)
add_subdirectory(platforms)
add_subdirectory(scenes)
if(KWIN_BUILD_DECORATIONS)
add_subdirectory(kdecorations)

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

@ -0,0 +1,25 @@
set(SCENE_XRENDER_SRCS scene_xrender.cpp)
include(ECMQtDeclareLoggingCategory)
ecm_qt_declare_logging_category(
SCENE_XRENDER_SRCS HEADER
logging.h
IDENTIFIER
KWIN_XRENDER
CATEGORY_NAME
kwin_scene_xrender
DEFAULT_SEVERITY
Critical
)
add_library(KWinSceneXRender MODULE ${SCENE_XRENDER_SRCS})
target_link_libraries(KWinSceneXRender
kwin
)
install(
TARGETS
KWinSceneXRender
DESTINATION
${PLUGIN_INSTALL_DIR}/org.kde.kwin.scenes/
)

@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
#include "logging.h"
#include "toplevel.h"
#include "client.h"
#include "composite.h"
@ -96,7 +97,7 @@ void XRenderBackend::setBuffer(xcb_render_picture_t buffer)
void XRenderBackend::setFailed(const QString& reason)
{
qCCritical(KWIN_CORE) << "Creating the XRender backend failed: " << reason;
qCCritical(KWIN_XRENDER) << "Creating the XRender backend failed: " << reason;
m_failed = true;
}
@ -1297,6 +1298,23 @@ void SceneXRenderDecorationRenderer::reparent(Deleted *deleted)
#undef DOUBLE_TO_FIXED
#undef FIXED_TO_DOUBLE
XRenderFactory::XRenderFactory(QObject *parent)
: SceneFactory(parent)
{
}
XRenderFactory::~XRenderFactory() = default;
Scene *XRenderFactory::create(QObject *parent) const
{
auto s = SceneXrender::createScene(parent);
if (s && s->initFailed()) {
delete s;
s = nullptr;
}
return s;
}
} // namespace
#endif

@ -341,6 +341,19 @@ private:
XRenderPicture* m_pictures[int(DecorationPart::Count)];
};
class KWIN_EXPORT XRenderFactory : public SceneFactory
{
Q_OBJECT
Q_INTERFACES(KWin::SceneFactory)
Q_PLUGIN_METADATA(IID "org.kde.kwin.Scene" FILE "xrender.json")
public:
explicit XRenderFactory(QObject *parent = nullptr);
~XRenderFactory() override;
Scene *create(QObject *parent = nullptr) const override;
};
} // namespace
#endif

@ -0,0 +1,8 @@
{
"KPlugin": {
"Description": "KWin Compositor plugin rendering through XRender",
"Id": "KWinSceneXRender",
"Name": "SceneXRender"
},
"CompositingType": 2
}

@ -1124,4 +1124,13 @@ Scene::EffectFrame::~EffectFrame()
{
}
SceneFactory::SceneFactory(QObject *parent)
: QObject(parent)
{
}
SceneFactory::~SceneFactory()
{
}
} // namespace

@ -245,6 +245,24 @@ private:
QVector< Window* > stacking_order;
};
/**
* Factory class to create a Scene. Needs to be implemented by the plugins.
**/
class KWIN_EXPORT SceneFactory : public QObject
{
Q_OBJECT
public:
virtual ~SceneFactory();
/**
* @returns The created Scene, may be @c nullptr.
**/
virtual Scene *create(QObject *parent = nullptr) const = 0;
protected:
explicit SceneFactory(QObject *parent);
};
// The base class for windows representations in composite backends
class Scene::Window
{
@ -359,7 +377,7 @@ private:
* This class is intended to be inherited for the needs of the compositor backends which need further mapping from
* the native pixmap to the respective rendering format.
*/
class WindowPixmap
class KWIN_EXPORT WindowPixmap
{
public:
virtual ~WindowPixmap();
@ -643,4 +661,6 @@ const QSize &WindowPixmap::size() const
} // namespace
Q_DECLARE_INTERFACE(KWin::SceneFactory, "org.kde.kwin.Scene")
#endif

@ -58,7 +58,7 @@ class Toplevel;
* @author Martin Gräßlin <mgraesslin@kde.org>
* @todo React on Toplevel size changes.
**/
class Shadow : public QObject
class KWIN_EXPORT Shadow : public QObject
{
Q_OBJECT
public:

Loading…
Cancel
Save