diff --git a/CMakeLists.txt b/CMakeLists.txt index c042ff78f7..108d646693 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 4bb816869e..d10913c44d 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 = 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); - - m_scene = SceneOpenGL::createScene(this); - - kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PostInit); - - if (m_scene && !m_scene->initFailed()) { - connect(static_cast(m_scene), &SceneOpenGL::resetCompositing, this, &Compositor::restart); - break; // --> + 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 factory{qobject_cast(pluginIt->instantiate())}; + if (factory) { + m_scene = factory->create(this); + if (m_scene) { + qCDebug(KWIN_CORE) << "Instantiated compositing plugin:" << pluginIt->name(); } - 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(); + + if (!m_scene) { + switch(options->compositingMode()) { + case OpenGLCompositing: { + qCDebug(KWIN_CORE) << "Initializing OpenGL compositing"; + + // 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); + + m_scene = SceneOpenGL::createScene(this); + + kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PostInit); + + if (m_scene && !m_scene->initFailed()) { + connect(static_cast(m_scene), &SceneOpenGL::resetCompositing, this, &Compositor::restart); + break; // --> + } + 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; } - 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 4f5d231d20..8900680251 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 e216e2687a..17d184bda9 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 ba24902b08..b9eb3d36a7 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 3a06fa63fb..da3eed351a 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 0000000000..b93ce5b957 --- /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 0000000000..8e8c67ed37 --- /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 4334807874..df1702699d 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 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 d4dacd3610..04bc66caea 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 0000000000..d2af878b9b --- /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 a51bbe9be2..bf5b7778d0 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 e7c885ac98..5d9865ecac 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 d47ff88b99..b64cf7a471 100644 --- a/shadow.h +++ b/shadow.h @@ -58,7 +58,7 @@ class Toplevel; * @author Martin Gräßlin * @todo React on Toplevel size changes. **/ -class Shadow : public QObject +class KWIN_EXPORT Shadow : public QObject { Q_OBJECT public: