File indexing completed on 2024-12-08 13:21:45
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2011 Arthur Arlt <a.arlt@stud.uni-heidelberg.de> 0006 SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 #pragma once 0011 0012 #include <kwinglobals.h> 0013 0014 #include <QObject> 0015 #include <QRegion> 0016 #include <QTimer> 0017 #include <memory> 0018 0019 namespace KWin 0020 { 0021 0022 class Output; 0023 class CompositorSelectionOwner; 0024 class CursorScene; 0025 class CursorView; 0026 class RenderBackend; 0027 class RenderLayer; 0028 class RenderLoop; 0029 class RenderTarget; 0030 class WorkspaceScene; 0031 class Window; 0032 class X11Window; 0033 class X11SyncManager; 0034 0035 class KWIN_EXPORT Compositor : public QObject 0036 { 0037 Q_OBJECT 0038 public: 0039 enum class State { 0040 On = 0, 0041 Off, 0042 Starting, 0043 Stopping 0044 }; 0045 0046 ~Compositor() override; 0047 static Compositor *self(); 0048 0049 /** 0050 * Schedules a new repaint if no repaint is currently scheduled. 0051 */ 0052 void scheduleRepaint(); 0053 0054 /** 0055 * Toggles compositing, that is if the Compositor is suspended it will be resumed 0056 * and if the Compositor is active it will be suspended. 0057 * Invoked by keybinding (shortcut default: Shift + Alt + F12). 0058 */ 0059 virtual void toggleCompositing() = 0; 0060 0061 /** 0062 * Re-initializes the Compositor completely. 0063 * Connected to the D-Bus signal org.kde.KWin /KWin reinitCompositing 0064 */ 0065 virtual void reinitialize(); 0066 0067 /** 0068 * Whether the Compositor is active. That is a Scene is present and the Compositor is 0069 * not shutting down itself. 0070 */ 0071 bool isActive(); 0072 0073 WorkspaceScene *scene() const 0074 { 0075 return m_scene.get(); 0076 } 0077 CursorScene *cursorScene() const 0078 { 0079 return m_cursorScene.get(); 0080 } 0081 RenderBackend *backend() const 0082 { 0083 return m_backend.get(); 0084 } 0085 0086 /** 0087 * @brief Static check to test whether the Compositor is available and active. 0088 * 0089 * @return bool @c true if there is a Compositor and it is active, @c false otherwise 0090 */ 0091 static bool compositing() 0092 { 0093 return s_compositor != nullptr && s_compositor->isActive(); 0094 } 0095 0096 // for delayed supportproperty management of effects 0097 void keepSupportProperty(xcb_atom_t atom); 0098 void removeSupportProperty(xcb_atom_t atom); 0099 0100 /** 0101 * Whether Compositing is possible in the Platform. 0102 * Returning @c false in this method makes only sense if requiresCompositing returns @c false. 0103 * 0104 * The default implementation returns @c true. 0105 * @see requiresCompositing 0106 */ 0107 virtual bool compositingPossible() const; 0108 /** 0109 * Returns a user facing text explaining why compositing is not possible in case 0110 * compositingPossible returns @c false. 0111 * 0112 * The default implementation returns an empty string. 0113 * @see compositingPossible 0114 */ 0115 virtual QString compositingNotPossibleReason() const; 0116 /** 0117 * Whether OpenGL compositing is broken. 0118 * The Platform can implement this method if it is able to detect whether OpenGL compositing 0119 * broke (e.g. triggered a crash in a previous run). 0120 * 0121 * Default implementation returns @c false. 0122 * @see createOpenGLSafePoint 0123 */ 0124 virtual bool openGLCompositingIsBroken() const; 0125 enum class OpenGLSafePoint { 0126 PreInit, 0127 PostInit, 0128 PreFrame, 0129 PostFrame, 0130 PostLastGuardedFrame 0131 }; 0132 /** 0133 * This method is invoked before and after creating the OpenGL rendering Scene. 0134 * An implementing Platform can use it to detect crashes triggered by the OpenGL implementation. 0135 * This can be used for openGLCompositingIsBroken. 0136 * 0137 * The default implementation does nothing. 0138 * @see openGLCompositingIsBroken. 0139 */ 0140 virtual void createOpenGLSafePoint(OpenGLSafePoint safePoint); 0141 0142 Q_SIGNALS: 0143 void compositingToggled(bool active); 0144 void aboutToDestroy(); 0145 void aboutToToggleCompositing(); 0146 void sceneCreated(); 0147 0148 protected: 0149 explicit Compositor(QObject *parent = nullptr); 0150 0151 virtual void start() = 0; 0152 virtual void stop(); 0153 0154 /** 0155 * @brief Prepares start. 0156 * @return bool @c true if start should be continued and @c if not. 0157 */ 0158 bool setupStart(); 0159 /** 0160 * Continues the startup after Scene And Workspace are created 0161 */ 0162 void startupWithWorkspace(); 0163 0164 virtual void configChanged(); 0165 0166 void destroyCompositorSelection(); 0167 0168 static Compositor *s_compositor; 0169 0170 protected Q_SLOTS: 0171 virtual void composite(RenderLoop *renderLoop); 0172 0173 private Q_SLOTS: 0174 void handleFrameRequested(RenderLoop *renderLoop); 0175 0176 private: 0177 void initializeX11(); 0178 void cleanupX11(); 0179 0180 void releaseCompositorSelection(); 0181 void deleteUnusedSupportProperties(); 0182 0183 bool attemptOpenGLCompositing(); 0184 bool attemptQPainterCompositing(); 0185 0186 Output *findOutput(RenderLoop *loop) const; 0187 void addOutput(Output *output); 0188 void removeOutput(Output *output); 0189 0190 void addSuperLayer(RenderLayer *layer); 0191 void removeSuperLayer(RenderLayer *layer); 0192 0193 void prePaintPass(RenderLayer *layer); 0194 void postPaintPass(RenderLayer *layer); 0195 void preparePaintPass(RenderLayer *layer, QRegion *repaint); 0196 void paintPass(RenderLayer *layer, RenderTarget *target, const QRegion ®ion); 0197 0198 State m_state = State::Off; 0199 std::unique_ptr<CompositorSelectionOwner> m_selectionOwner; 0200 QTimer m_releaseSelectionTimer; 0201 QList<xcb_atom_t> m_unusedSupportProperties; 0202 QTimer m_unusedSupportPropertyTimer; 0203 std::unique_ptr<WorkspaceScene> m_scene; 0204 std::unique_ptr<CursorScene> m_cursorScene; 0205 std::unique_ptr<RenderBackend> m_backend; 0206 QHash<RenderLoop *, RenderLayer *> m_superlayers; 0207 CompositingType m_selectedCompositor = NoCompositing; 0208 }; 0209 0210 class KWIN_EXPORT WaylandCompositor final : public Compositor 0211 { 0212 Q_OBJECT 0213 public: 0214 static WaylandCompositor *create(QObject *parent = nullptr); 0215 ~WaylandCompositor() override; 0216 0217 void toggleCompositing() override; 0218 0219 protected: 0220 void start() override; 0221 0222 private: 0223 explicit WaylandCompositor(QObject *parent); 0224 }; 0225 0226 class KWIN_EXPORT X11Compositor final : public Compositor 0227 { 0228 Q_OBJECT 0229 public: 0230 enum SuspendReason { 0231 NoReasonSuspend = 0, 0232 UserSuspend = 1 << 0, 0233 BlockRuleSuspend = 1 << 1, 0234 ScriptSuspend = 1 << 2, 0235 AllReasonSuspend = 0xff 0236 }; 0237 Q_DECLARE_FLAGS(SuspendReasons, SuspendReason) 0238 Q_ENUM(SuspendReason) 0239 Q_FLAG(SuspendReasons) 0240 0241 static X11Compositor *create(QObject *parent = nullptr); 0242 ~X11Compositor() override; 0243 0244 X11SyncManager *syncManager() const; 0245 0246 /** 0247 * @brief Suspends the Compositor if it is currently active. 0248 * 0249 * Note: it is possible that the Compositor is not able to suspend. Use isActive to check 0250 * whether the Compositor has been suspended. 0251 * 0252 * @return void 0253 * @see resume 0254 * @see isActive 0255 */ 0256 void suspend(SuspendReason reason); 0257 0258 /** 0259 * @brief Resumes the Compositor if it is currently suspended. 0260 * 0261 * Note: it is possible that the Compositor cannot be resumed, that is there might be Clients 0262 * blocking the usage of Compositing or the Scene might be broken. Use isActive to check 0263 * whether the Compositor has been resumed. Also check isCompositingPossible and 0264 * isOpenGLBroken. 0265 * 0266 * Note: The starting of the Compositor can require some time and is partially done threaded. 0267 * After this method returns the setup may not have been completed. 0268 * 0269 * @return void 0270 * @see suspend 0271 * @see isActive 0272 * @see isCompositingPossible 0273 * @see isOpenGLBroken 0274 */ 0275 void resume(SuspendReason reason); 0276 0277 void toggleCompositing() override; 0278 void reinitialize() override; 0279 void configChanged() override; 0280 bool compositingPossible() const override; 0281 QString compositingNotPossibleReason() const override; 0282 bool openGLCompositingIsBroken() const override; 0283 void createOpenGLSafePoint(OpenGLSafePoint safePoint) override; 0284 0285 /** 0286 * Checks whether @p w is the Scene's overlay window. 0287 */ 0288 bool checkForOverlayWindow(WId w) const; 0289 0290 /** 0291 * @returns Whether the Scene's Overlay X Window is visible. 0292 */ 0293 bool isOverlayWindowVisible() const; 0294 0295 void updateClientCompositeBlocking(X11Window *client = nullptr); 0296 0297 static X11Compositor *self(); 0298 0299 protected: 0300 void start() override; 0301 void stop() override; 0302 void composite(RenderLoop *renderLoop) override; 0303 0304 private: 0305 explicit X11Compositor(QObject *parent); 0306 0307 std::unique_ptr<QThread> m_openGLFreezeProtectionThread; 0308 std::unique_ptr<QTimer> m_openGLFreezeProtection; 0309 std::unique_ptr<X11SyncManager> m_syncManager; 0310 /** 0311 * Whether the Compositor is currently suspended, 8 bits encoding the reason 0312 */ 0313 SuspendReasons m_suspended; 0314 int m_framesToTestForSafety = 3; 0315 }; 0316 0317 }