[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kwin] /: Move SceneXRender into a plugin
From:       Martin_Flöser <null () kde ! org>
Date:       2017-09-01 16:06:13
Message-ID: E1dnoST-0008Ko-L5 () code ! kde ! org
[Download RAW message or body]

Git commit 054d9234112ca4faa0f563be5012c74286b9c806 by Martin Flöser.
Committed on 01/09/2017 at 15:42.
Pushed by graesslin into branch 'master'.

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

M  +0    -1    CMakeLists.txt
M  +61   -41   composite.cpp
M  +1    -0    data/org_kde_kwin.categories
M  +3    -1    decorations/decorationrenderer.h
M  +1    -1    effects.h
M  +1    -0    plugins/CMakeLists.txt
A  +3    -0    plugins/scenes/CMakeLists.txt
A  +25   -0    plugins/scenes/xrender/CMakeLists.txt
R  +19   -1    plugins/scenes/xrender/scene_xrender.cpp [from: scene_xrender.cpp - \
099% similarity] R  +13   -0    plugins/scenes/xrender/scene_xrender.h [from: \
scene_xrender.h - 096% similarity] A  +8    -0    plugins/scenes/xrender/xrender.json
M  +9    -0    scene.cpp
M  +21   -1    scene.h
M  +1    -1    shadow.h

https://commits.kde.org/kwin/054d9234112ca4faa0f563be5012c74286b9c806

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c042ff78f..108d64669 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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
diff --git a/composite.cpp b/composite.cpp
index 4bb816869..d10913c44 100644
--- a/composite.cpp
+++ b/composite.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";
diff --git a/data/org_kde_kwin.categories b/data/org_kde_kwin.categories
index 4f5d231d2..890068025 100644
--- a/data/org_kde_kwin.categories
+++ b/data/org_kde_kwin.categories
@@ -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
diff --git a/decorations/decorationrenderer.h b/decorations/decorationrenderer.h
index e216e2687..17d184bda 100644
--- a/decorations/decorationrenderer.h
+++ b/decorations/decorationrenderer.h
@@ -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:
diff --git a/effects.h b/effects.h
index ba24902b0..b9eb3d36a 100644
--- a/effects.h
+++ b/effects.h
@@ -393,7 +393,7 @@ private:
     Group* group;
 };
 
-class EffectFrameImpl
+class KWIN_EXPORT EffectFrameImpl
     : public QObject, public EffectFrame
 {
     Q_OBJECT
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
index 3a06fa63f..da3eed351 100644
--- a/plugins/CMakeLists.txt
+++ b/plugins/CMakeLists.txt
@@ -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)
diff --git a/plugins/scenes/CMakeLists.txt b/plugins/scenes/CMakeLists.txt
new file mode 100644
index 000000000..b93ce5b95
--- /dev/null
+++ b/plugins/scenes/CMakeLists.txt
@@ -0,0 +1,3 @@
+if( KWIN_BUILD_XRENDER_COMPOSITING )
+    add_subdirectory(xrender)
+endif()
diff --git a/plugins/scenes/xrender/CMakeLists.txt \
b/plugins/scenes/xrender/CMakeLists.txt new file mode 100644
index 000000000..8e8c67ed3
--- /dev/null
+++ b/plugins/scenes/xrender/CMakeLists.txt
@@ -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/
+)
diff --git a/scene_xrender.cpp b/plugins/scenes/xrender/scene_xrender.cpp
similarity index 99%
rename from scene_xrender.cpp
rename to plugins/scenes/xrender/scene_xrender.cpp
index 433480787..df1702699 100644
--- a/scene_xrender.cpp
+++ b/plugins/scenes/xrender/scene_xrender.cpp
@@ -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
 
diff --git a/scene_xrender.h b/plugins/scenes/xrender/scene_xrender.h
similarity index 96%
rename from scene_xrender.h
rename to plugins/scenes/xrender/scene_xrender.h
index d4dacd361..04bc66cae 100644
--- a/scene_xrender.h
+++ b/plugins/scenes/xrender/scene_xrender.h
@@ -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
diff --git a/plugins/scenes/xrender/xrender.json \
b/plugins/scenes/xrender/xrender.json new file mode 100644
index 000000000..d2af878b9
--- /dev/null
+++ b/plugins/scenes/xrender/xrender.json
@@ -0,0 +1,8 @@
+{
+    "KPlugin": {
+        "Description": "KWin Compositor plugin rendering through XRender",
+        "Id": "KWinSceneXRender",
+        "Name": "SceneXRender"
+    },
+    "CompositingType": 2
+}
diff --git a/scene.cpp b/scene.cpp
index a51bbe9be..bf5b7778d 100644
--- a/scene.cpp
+++ b/scene.cpp
@@ -1124,4 +1124,13 @@ Scene::EffectFrame::~EffectFrame()
 {
 }
 
+SceneFactory::SceneFactory(QObject *parent)
+    : QObject(parent)
+{
+}
+
+SceneFactory::~SceneFactory()
+{
+}
+
 } // namespace
diff --git a/scene.h b/scene.h
index e7c885ac9..5d9865eca 100644
--- a/scene.h
+++ b/scene.h
@@ -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
diff --git a/shadow.h b/shadow.h
index d47ff88b9..b64cf7a47 100644
--- a/shadow.h
+++ b/shadow.h
@@ -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:


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic