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
This commit is contained in:
parent
1e13deaa1d
commit
054d923411
14 changed files with 168 additions and 49 deletions
|
@ -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
|
||||
|
|
106
composite.cpp
106
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);
|
||||
|
||||
m_scene = SceneOpenGL::createScene(this);
|
||||
|
||||
kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PostInit);
|
||||
|
||||
if (m_scene && !m_scene->initFailed()) {
|
||||
connect(static_cast<SceneOpenGL*>(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<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();
|
||||
}
|
||||
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<SceneOpenGL*>(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";
|
||||
|
|
|
@ -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)
|
||||
|
|
3
plugins/scenes/CMakeLists.txt
Normal file
3
plugins/scenes/CMakeLists.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
if( KWIN_BUILD_XRENDER_COMPOSITING )
|
||||
add_subdirectory(xrender)
|
||||
endif()
|
25
plugins/scenes/xrender/CMakeLists.txt
Normal file
25
plugins/scenes/xrender/CMakeLists.txt
Normal file
|
@ -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
|
8
plugins/scenes/xrender/xrender.json
Normal file
8
plugins/scenes/xrender/xrender.json
Normal file
|
@ -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
|
||||
|
|
22
scene.h
22
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
|
||||
|
|
2
shadow.h
2
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:
|
||||
|
|
Loading…
Reference in a new issue