From kde-commits Fri Sep 01 16:06:13 2017 From: =?utf-8?q?Martin_Fl=C3=B6ser?= Date: Fri, 01 Sep 2017 16:06:13 +0000 To: kde-commits Subject: [kwin] /: Move SceneXRender into a plugin Message-Id: X-MARC-Message: https://marc.info/?l=kde-commits&m=150428198918257 Git commit 054d9234112ca4faa0f563be5012c74286b9c806 by Martin Fl=C3=B6ser. 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_xrende= r.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 . #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 . #include #include #include +#include +#include #include #include = @@ -199,54 +200,73 @@ void Compositor::slotCompositingOptionsInitialized() } } = - switch(options->compositingMode()) { - case OpenGLCompositing: { - qCDebug(KWIN_CORE) << "Initializing OpenGL compositing"; + const auto availablePlugins =3D KPluginLoader::findPlugins(QStringLite= ral("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 li= brary is unsafe to use"; - else { - kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLS= afePoint::PreInit); + const auto pluginIt =3D std::find_if(availablePlugins.begin(), availab= lePlugins.end(), + [] (const auto &plugin) { + const auto &metaData =3D plugin.rawData(); + auto it =3D metaData.find(QStringLiteral("CompositingType")); + if (it !=3D metaData.end()) { + if ((*it).toInt() =3D=3D int{options->compositingMode()}) { + return true; + } + } + return false; + }); + if (pluginIt !=3D availablePlugins.end()) { + std::unique_ptr factory{qobject_cast(= pluginIt->instantiate())}; + if (factory) { + m_scene =3D 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 =3D SceneOpenGL::createScene(this); + // Some broken drivers crash on glXQuery() so to prevent const= ant KWin crashes: + if (kwinApp()->platform()->openGLCompositingIsBroken()) + qCWarning(KWIN_CORE) << "KWin has detected that your OpenG= L library is unsafe to use"; + else { + kwinApp()->platform()->createOpenGLSafePoint(Platform::Ope= nGLSafePoint::PreInit); = - kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLS= afePoint::PostInit); + m_scene =3D SceneOpenGL::createScene(this); = - if (m_scene && !m_scene->initFailed()) { - connect(static_cast(m_scene), &SceneOpenGL::= resetCompositing, this, &Compositor::restart); - break; // --> + kwinApp()->platform()->createOpenGLSafePoint(Platform::Ope= nGLSafePoint::PostInit); + + if (m_scene && !m_scene->initFailed()) { + connect(static_cast(m_scene), &SceneOpen= GL::resetCompositing, this, &Compositor::restart); + break; // --> + } + delete m_scene; + m_scene =3D NULL; } - delete m_scene; - m_scene =3D 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 =3D SceneXrender::createScene(this); - break; -#endif - case QPainterCompositing: - qCDebug(KWIN_CORE) << "Initializing QPainter compositing"; - m_scene =3D SceneQPainter::createScene(this); - break; - default: - qCDebug(KWIN_CORE) << "No compositing enabled"; - m_starting =3D false; - if (cm_selection) { - cm_selection->owning =3D false; - cm_selection->release(); + // Do not Fall back to XRender - it causes problems when selfc= heck fails during startup, but works later on + break; } - if (kwinApp()->platform()->requiresCompositing()) { - qCCritical(KWIN_CORE) << "The used windowing system requires c= ompositing"; - 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 =3D SceneQPainter::createScene(this); + break; + default: + qCDebug(KWIN_CORE) << "No compositing enabled"; + m_starting =3D false; + if (cm_selection) { + cm_selection->owning =3D false; + cm_selection->release(); + } + if (kwinApp()->platform()->requiresCompositing()) { + qCCritical(KWIN_CORE) << "The used windowing system requir= es compositing"; + qCCritical(KWIN_CORE) << "We are going to quit KWin now as= it is broken"; + qApp->quit(); + } + return; } - return; } if (m_scene =3D=3D NULL || m_scene->initFailed()) { qCCritical(KWIN_CORE) << "Failed to initialize compositing, compos= iting 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/decorationrende= rer.h index e216e2687..17d184bda 100644 --- a/decorations/decorationrenderer.h +++ b/decorations/decorationrenderer.h @@ -25,6 +25,8 @@ along with this program. If not, see . = #include = +#include + 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 . = #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 buffe= r) = void XRenderBackend::setFailed(const QString& reason) { - qCCritical(KWIN_CORE) << "Creating the XRender backend failed: " << re= ason; + qCCritical(KWIN_XRENDER) << "Creating the XRender backend failed: " <<= reason; m_failed =3D true; } = @@ -1297,6 +1298,23 @@ void SceneXRenderDecorationRenderer::reparent(Delete= d *deleted) #undef DOUBLE_TO_FIXED #undef FIXED_TO_DOUBLE = +XRenderFactory::XRenderFactory(QObject *parent) + : SceneFactory(parent) +{ +} + +XRenderFactory::~XRenderFactory() =3D default; + +Scene *XRenderFactory::create(QObject *parent) const +{ + auto s =3D SceneXrender::createScene(parent); + if (s && s->initFailed()) { + delete s; + s =3D 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 =3D nullptr); + ~XRenderFactory() override; + + Scene *create(QObject *parent =3D nullptr) const override; +}; + } // namespace = #endif diff --git a/plugins/scenes/xrender/xrender.json b/plugins/scenes/xrender/x= render.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 =3D nullptr) const =3D 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=C3=A4=C3=9Flin * @todo React on Toplevel size changes. **/ -class Shadow : public QObject +class KWIN_EXPORT Shadow : public QObject { Q_OBJECT public: