From 4d2c9f5d886f796dd690b8ad1e1761ae74bd2e66 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Mon, 18 Sep 2023 13:40:33 +0000 Subject: [PATCH] Refactor compositing config loading Config loading is split in two groups: loading compositing config and loading the rest. They are loaded separately at different times. Some options are loaded in the Options constructor, some are loaded when compositing starts, some are loaded when the Workspace is created. It's not easy to keep track of what loads what and when. This change simplifies option handling by loading all options in bulk and decouples Options from OutputBackend and GLPlatform to ensure that it can safely load options before kwin is fully operational. --- .../standalone/x11_standalone_egl_backend.cpp | 14 +- .../standalone/x11_standalone_egl_backend.h | 2 + .../standalone/x11_standalone_glx_backend.cpp | 17 ++- .../standalone/x11_standalone_glx_backend.h | 2 + src/compositor.cpp | 2 - src/main_wayland.cpp | 1 - src/main_x11.cpp | 1 - src/options.cpp | 131 ++++++------------ src/options.h | 5 - .../scenes/opengl/abstract_egl_backend.cpp | 6 +- src/workspace.cpp | 11 -- 11 files changed, 72 insertions(+), 120 deletions(-) diff --git a/src/backends/x11/standalone/x11_standalone_egl_backend.cpp b/src/backends/x11/standalone/x11_standalone_egl_backend.cpp index 8e98baca20..78a2d8983c 100644 --- a/src/backends/x11/standalone/x11_standalone_egl_backend.cpp +++ b/src/backends/x11/standalone/x11_standalone_egl_backend.cpp @@ -174,6 +174,18 @@ void EglBackend::init() qCWarning(KWIN_CORE) << "eglPostSubBufferNV not supported, have to enable buffer preservation - which breaks v-sync and performance"; eglSurfaceAttrib(eglDisplayObject()->handle(), surface(), EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); } + + m_swapStrategy = options->glPreferBufferSwap(); + if (m_swapStrategy == Options::AutoSwapStrategy) { + // buffer copying is very fast with the nvidia blob + // but due to restrictions in DRI2 *incredibly* slow for all MESA drivers + // see https://www.x.org/releases/X11R7.7/doc/dri2proto/dri2proto.txt, item 2.5 + if (GLPlatform::instance()->driver() == Driver_NVidia) { + m_swapStrategy = Options::CopyFrontBuffer; + } else if (GLPlatform::instance()->driver() != Driver_Unknown) { // undetected, finally resolved when context is initialized + m_swapStrategy = Options::ExtendDamage; + } + } } bool EglBackend::initRenderingContext() @@ -358,7 +370,7 @@ void EglBackend::present(Output *output) QRegion effectiveRenderedRegion = m_lastRenderedRegion; if (!GLPlatform::instance()->isGLES()) { const QRect displayRect = workspace()->geometry(); - if (!supportsBufferAge() && options->glPreferBufferSwap() == Options::CopyFrontBuffer && m_lastRenderedRegion != displayRect) { + if (!supportsBufferAge() && m_swapStrategy == Options::CopyFrontBuffer && m_lastRenderedRegion != displayRect) { glReadBuffer(GL_FRONT); copyPixels(QRegion(displayRect) - m_lastRenderedRegion, displayRect.size()); glReadBuffer(GL_BACK); diff --git a/src/backends/x11/standalone/x11_standalone_egl_backend.h b/src/backends/x11/standalone/x11_standalone_egl_backend.h index 41eadaa29c..1aebc07382 100644 --- a/src/backends/x11/standalone/x11_standalone_egl_backend.h +++ b/src/backends/x11/standalone/x11_standalone_egl_backend.h @@ -7,6 +7,7 @@ #pragma once #include "core/outputlayer.h" +#include "options.h" #include "platformsupport/scenes/opengl/abstract_egl_backend.h" #include "platformsupport/scenes/opengl/openglsurfacetexture_x11.h" #include "utils/damagejournal.h" @@ -78,6 +79,7 @@ private: std::unique_ptr m_query; int m_havePostSubBuffer = false; bool m_havePlatformBase = false; + Options::GlSwapStrategy m_swapStrategy = Options::AutoSwapStrategy; }; class EglPixmapTexture : public GLTexture diff --git a/src/backends/x11/standalone/x11_standalone_glx_backend.cpp b/src/backends/x11/standalone/x11_standalone_glx_backend.cpp index b13c43d19a..9920eedc44 100644 --- a/src/backends/x11/standalone/x11_standalone_glx_backend.cpp +++ b/src/backends/x11/standalone/x11_standalone_glx_backend.cpp @@ -225,10 +225,19 @@ void GlxBackend::init() // Initialize OpenGL GLPlatform *glPlatform = GLPlatform::instance(); glPlatform->detect(GlxPlatformInterface); - options->setGlPreferBufferSwap(options->glPreferBufferSwap()); // resolve autosetting - if (options->glPreferBufferSwap() == Options::AutoSwapStrategy) { - options->setGlPreferBufferSwap('e'); // for unknown drivers - should not happen + + m_swapStrategy = options->glPreferBufferSwap(); + if (m_swapStrategy == Options::AutoSwapStrategy) { + // buffer copying is very fast with the nvidia blob + // but due to restrictions in DRI2 *incredibly* slow for all MESA drivers + // see https://www.x.org/releases/X11R7.7/doc/dri2proto/dri2proto.txt, item 2.5 + if (GLPlatform::instance()->driver() == Driver_NVidia) { + m_swapStrategy = Options::CopyFrontBuffer; + } else if (GLPlatform::instance()->driver() != Driver_Unknown) { // undetected, finally resolved when context is initialized + m_swapStrategy = Options::ExtendDamage; + } } + glPlatform->printResults(); initGL(&getProcAddress); @@ -731,7 +740,7 @@ void GlxBackend::present(Output *output) const QRect displayRect = workspace()->geometry(); QRegion effectiveRenderedRegion = m_lastRenderedRegion; - if (!supportsBufferAge() && options->glPreferBufferSwap() == Options::CopyFrontBuffer && m_lastRenderedRegion != displayRect) { + if (!supportsBufferAge() && m_swapStrategy == Options::CopyFrontBuffer && m_lastRenderedRegion != displayRect) { glReadBuffer(GL_FRONT); copyPixels(QRegion(displayRect) - m_lastRenderedRegion, displayRect.size()); glReadBuffer(GL_BACK); diff --git a/src/backends/x11/standalone/x11_standalone_glx_backend.h b/src/backends/x11/standalone/x11_standalone_glx_backend.h index 1a37769a7c..a751d240da 100644 --- a/src/backends/x11/standalone/x11_standalone_glx_backend.h +++ b/src/backends/x11/standalone/x11_standalone_glx_backend.h @@ -8,6 +8,7 @@ */ #pragma once #include "core/outputlayer.h" +#include "options.h" #include "platformsupport/scenes/opengl/openglbackend.h" #include "platformsupport/scenes/opengl/openglsurfacetexture_x11.h" #include "utils/damagejournal.h" @@ -138,6 +139,7 @@ private: std::unique_ptr m_vsyncMonitor; std::unique_ptr m_layer; std::unique_ptr m_query; + Options::GlSwapStrategy m_swapStrategy = Options::AutoSwapStrategy; friend class GlxPixmapTexture; }; diff --git a/src/compositor.cpp b/src/compositor.cpp index 16d3820923..b9ff67a197 100644 --- a/src/compositor.cpp +++ b/src/compositor.cpp @@ -204,8 +204,6 @@ bool Compositor::setupStart() } m_state = State::Starting; - options->reloadCompositingSettings(true); - initializeX11(); Q_EMIT aboutToToggleCompositing(); diff --git a/src/main_wayland.cpp b/src/main_wayland.cpp index fbc5cecea9..b3d496045e 100644 --- a/src/main_wayland.cpp +++ b/src/main_wayland.cpp @@ -134,7 +134,6 @@ void ApplicationWayland::performStartup() setOperationMode(OperationModeXwayland); setXwaylandScale(config()->group("Xwayland").readEntry("Scale", 1.0)); } - // first load options - done internally by a different thread createOptions(); if (!outputBackend()->initialize()) { diff --git a/src/main_x11.cpp b/src/main_x11.cpp index e9ad7fa980..3cb2952bff 100644 --- a/src/main_x11.cpp +++ b/src/main_x11.cpp @@ -259,7 +259,6 @@ void ApplicationX11::performStartup() connect(owner.get(), &KSelectionOwner::lostOwnership, this, &ApplicationX11::lostSelection); connect(owner.get(), &KSelectionOwner::claimedOwnership, this, [this] { installNativeX11EventFilter(); - // first load options - done internally by a different thread createOptions(); if (!outputBackend()->initialize()) { diff --git a/src/options.cpp b/src/options.cpp index 897a7ddc76..3849d453a2 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -12,14 +12,12 @@ #include "config-kwin.h" -#include "core/outputbackend.h" #include "utils/common.h" #ifndef KCMRULES #include -#include "libkwineffects/glplatform.h" #include "settings.h" #include "workspace.h" #include @@ -92,7 +90,8 @@ Options::Options(QObject *parent) , condensed_title(false) { m_settings->setDefaults(); - syncFromKcfgc(); + + loadConfig(); m_configWatcher = KConfigWatcher::create(m_settings->sharedConfig()); connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group, const QByteArrayList &names) { @@ -612,16 +611,6 @@ void Options::setWindowsBlockCompositing(bool value) void Options::setGlPreferBufferSwap(char glPreferBufferSwap) { - if (glPreferBufferSwap == 'a') { - // buffer copying is very fast with the nvidia blob - // but due to restrictions in DRI2 *incredibly* slow for all MESA drivers - // see https://www.x.org/releases/X11R7.7/doc/dri2proto/dri2proto.txt, item 2.5 - if (GLPlatform::instance()->driver() == Driver_NVidia) { - glPreferBufferSwap = CopyFrontBuffer; - } else if (GLPlatform::instance()->driver() != Driver_Unknown) { // undetected, finally resolved when context is initialized - glPreferBufferSwap = ExtendDamage; - } - } if (m_glPreferBufferSwap == (GlSwapStrategy)glPreferBufferSwap) { return; } @@ -715,16 +704,6 @@ void Options::reparseConfiguration() void Options::updateSettings() { loadConfig(); - // Read button tooltip animation effect from kdeglobals - // Since we want to allow users to enable window decoration tooltips - // and not kstyle tooltips and vise-versa, we don't read the - // "EffectNoTooltip" setting from kdeglobals. - - // QToolTip::setGloballyEnabled( d->show_tooltips ); - // KDE4 this probably needs to be done manually in clients - - // Driver-specific config detection - reloadCompositingSettings(); Q_EMIT configChanged(); } @@ -775,48 +754,9 @@ void Options::loadConfig() m_modifierOnlyShortcuts.insert(Qt::AltModifier, config.readEntry("Alt", QStringList())); } m_modifierOnlyShortcuts.insert(Qt::MetaModifier, config.readEntry("Meta", QStringList{QStringLiteral("org.kde.plasmashell"), QStringLiteral("/PlasmaShell"), QStringLiteral("org.kde.PlasmaShell"), QStringLiteral("activateLauncherMenu")})); -} - -void Options::syncFromKcfgc() -{ - setCondensedTitle(m_settings->condensedTitle()); - setFocusPolicy(m_settings->focusPolicy()); - setNextFocusPrefersMouse(m_settings->nextFocusPrefersMouse()); - setSeparateScreenFocus(m_settings->separateScreenFocus()); - setActiveMouseScreen(m_settings->activeMouseScreen()); - setRollOverDesktops(m_settings->rollOverDesktops()); - setFocusStealingPreventionLevel(m_settings->focusStealingPreventionLevel()); - setActivationDesktopPolicy(m_settings->activationDesktopPolicy()); - setXwaylandCrashPolicy(m_settings->xwaylandCrashPolicy()); - setXwaylandMaxCrashCount(m_settings->xwaylandMaxCrashCount()); - setXwaylandEavesdrops(XwaylandEavesdropsMode(m_settings->xwaylandEavesdrops())); - setPlacement(m_settings->placement()); - setAutoRaise(m_settings->autoRaise()); - setAutoRaiseInterval(m_settings->autoRaiseInterval()); - setDelayFocusInterval(m_settings->delayFocusInterval()); - setShadeHover(m_settings->shadeHover()); - setShadeHoverInterval(m_settings->shadeHoverInterval()); - setClickRaise(m_settings->clickRaise()); - setBorderSnapZone(m_settings->borderSnapZone()); - setWindowSnapZone(m_settings->windowSnapZone()); - setCenterSnapZone(m_settings->centerSnapZone()); - setSnapOnlyWhenOverlapping(m_settings->snapOnlyWhenOverlapping()); - setKillPingTimeout(m_settings->killPingTimeout()); - setHideUtilityWindowsForInactive(m_settings->hideUtilityWindowsForInactive()); - setBorderlessMaximizedWindows(m_settings->borderlessMaximizedWindows()); - setElectricBorderMaximize(m_settings->electricBorderMaximize()); - setElectricBorderTiling(m_settings->electricBorderTiling()); - setElectricBorderCornerRatio(m_settings->electricBorderCornerRatio()); - setWindowsBlockCompositing(m_settings->windowsBlockCompositing()); - setLatencyPolicy(m_settings->latencyPolicy()); - setRenderTimeEstimator(m_settings->renderTimeEstimator()); - setAllowTearing(m_settings->allowTearing()); -} - -bool Options::loadCompositingConfig(bool force) -{ - KConfigGroup config(m_settings->config(), "Compositing"); + // Compositing + config = KConfigGroup(m_settings->config(), "Compositing"); bool useCompositing = false; CompositingType compositingMode = NoCompositing; QString compositingBackend = config.readEntry("Backend", "OpenGL"); @@ -852,32 +792,7 @@ bool Options::loadCompositingConfig(bool force) } } setCompositingMode(compositingMode); - - const bool platformSupportsNoCompositing = kwinApp()->outputBackend()->supportedCompositors().contains(NoCompositing); - if (m_compositingMode == NoCompositing && platformSupportsNoCompositing) { - setUseCompositing(false); - return false; // do not even detect compositing preferences if explicitly disabled - } - - // it's either enforced by env or by initial resume from "suspend" or we check the settings - setUseCompositing(useCompositing || force || config.readEntry("Enabled", Options::defaultUseCompositing() || !platformSupportsNoCompositing)); - - if (!m_useCompositing) { - return false; // not enforced or necessary and not "enabled" by settings - } - return true; -} - -void Options::reloadCompositingSettings(bool force) -{ - if (!loadCompositingConfig(force)) { - return; - } - m_settings->load(); - syncFromKcfgc(); - - // Compositing settings - KConfigGroup config(m_settings->config(), "Compositing"); + setUseCompositing(useCompositing || config.readEntry("Enabled", Options::defaultUseCompositing())); setGlSmoothScale(std::clamp(config.readEntry("GLTextureFilter", Options::defaultGlSmoothScale()), -1, 2)); setGlStrictBindingFollowsDriver(!config.hasKey("GLStrictBinding")); @@ -928,6 +843,42 @@ void Options::reloadCompositingSettings(bool force) setGlPlatformInterface(keyToInterface(config.readEntry("GLPlatformInterface", interfaceToKey(m_glPlatformInterface)))); } +void Options::syncFromKcfgc() +{ + setCondensedTitle(m_settings->condensedTitle()); + setFocusPolicy(m_settings->focusPolicy()); + setNextFocusPrefersMouse(m_settings->nextFocusPrefersMouse()); + setSeparateScreenFocus(m_settings->separateScreenFocus()); + setActiveMouseScreen(m_settings->activeMouseScreen()); + setRollOverDesktops(m_settings->rollOverDesktops()); + setFocusStealingPreventionLevel(m_settings->focusStealingPreventionLevel()); + setActivationDesktopPolicy(m_settings->activationDesktopPolicy()); + setXwaylandCrashPolicy(m_settings->xwaylandCrashPolicy()); + setXwaylandMaxCrashCount(m_settings->xwaylandMaxCrashCount()); + setXwaylandEavesdrops(XwaylandEavesdropsMode(m_settings->xwaylandEavesdrops())); + setPlacement(m_settings->placement()); + setAutoRaise(m_settings->autoRaise()); + setAutoRaiseInterval(m_settings->autoRaiseInterval()); + setDelayFocusInterval(m_settings->delayFocusInterval()); + setShadeHover(m_settings->shadeHover()); + setShadeHoverInterval(m_settings->shadeHoverInterval()); + setClickRaise(m_settings->clickRaise()); + setBorderSnapZone(m_settings->borderSnapZone()); + setWindowSnapZone(m_settings->windowSnapZone()); + setCenterSnapZone(m_settings->centerSnapZone()); + setSnapOnlyWhenOverlapping(m_settings->snapOnlyWhenOverlapping()); + setKillPingTimeout(m_settings->killPingTimeout()); + setHideUtilityWindowsForInactive(m_settings->hideUtilityWindowsForInactive()); + setBorderlessMaximizedWindows(m_settings->borderlessMaximizedWindows()); + setElectricBorderMaximize(m_settings->electricBorderMaximize()); + setElectricBorderTiling(m_settings->electricBorderTiling()); + setElectricBorderCornerRatio(m_settings->electricBorderCornerRatio()); + setWindowsBlockCompositing(m_settings->windowsBlockCompositing()); + setLatencyPolicy(m_settings->latencyPolicy()); + setRenderTimeEstimator(m_settings->renderTimeEstimator()); + setAllowTearing(m_settings->allowTearing()); +} + // restricted should be true for operations that the user may not be able to repeat // if the window is moved out of the workspace (e.g. if the user moves a window // by the titlebar, and moves it too high beneath Kicker at the top edge, they diff --git a/src/options.h b/src/options.h index 2b1f6e17cb..f2741a4bc7 100644 --- a/src/options.h +++ b/src/options.h @@ -640,7 +640,6 @@ public: //---------------------- // Compositing settings - void reloadCompositingSettings(bool force = false); CompositingType compositingMode() const { return m_compositingMode; @@ -903,10 +902,6 @@ public: * Performs loading all settings except compositing related. */ void loadConfig(); - /** - * Performs loading of compositing settings which do not depend on OpenGL. - */ - bool loadCompositingConfig(bool force); void reparseConfiguration(); //---------------------- diff --git a/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp b/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp index 4f300591f6..b0118e60c4 100644 --- a/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp +++ b/src/platformsupport/scenes/opengl/abstract_egl_backend.cpp @@ -9,7 +9,7 @@ #include "platformsupport/scenes/opengl/abstract_egl_backend.h" #include "compositor.h" #include "core/outputbackend.h" -#include "options.h" +#include "main.h" #include "utils/common.h" #include "utils/egl_context_attribute_builder.h" #include "wayland/drmclientbuffer.h" @@ -115,10 +115,6 @@ void AbstractEglBackend::initKWinGL() { GLPlatform *glPlatform = GLPlatform::instance(); glPlatform->detect(EglPlatformInterface); - options->setGlPreferBufferSwap(options->glPreferBufferSwap()); // resolve autosetting - if (options->glPreferBufferSwap() == Options::AutoSwapStrategy) { - options->setGlPreferBufferSwap('e'); // for unknown drivers - should not happen - } glPlatform->printResults(); initGL(&getProcAddress); } diff --git a/src/workspace.cpp b/src/workspace.cpp index 3b3900478b..15e1923087 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -64,8 +64,6 @@ #include #include #include -// Qt -#include // xcb #include @@ -133,9 +131,6 @@ Workspace::Workspace() , m_outputConfigStore(std::make_unique()) , m_lidSwitchTracker(std::make_unique()) { - // If KWin was already running it saved its configuration after loosing the selection -> Reread - QFuture reparseConfigFuture = QtConcurrent::run(&Options::reparseConfiguration, options); - _self = this; #if KWIN_BUILD_ACTIVITIES @@ -147,12 +142,6 @@ Workspace::Workspace() } #endif - // PluginMgr needs access to the config file, so we need to wait for it for finishing - reparseConfigFuture.waitForFinished(); - - options->loadConfig(); - options->loadCompositingConfig(false); - delayFocusTimer = nullptr; m_quickTileCombineTimer = new QTimer(this);