diff --git a/composite.cpp b/composite.cpp index 950ed10a22..c9df4de3ae 100644 --- a/composite.cpp +++ b/composite.cpp @@ -539,7 +539,7 @@ void Compositor::lastFrameRendered() void Compositor::performCompositing() { - if (!isOverlayWindowVisible()) + if (m_scene->usesOverlayWindow() && !isOverlayWindowVisible()) return; // nothing is visible anyway if (!m_scene->isLastFrameRendered()) { m_waitingForFrameRendered = true; @@ -706,7 +706,7 @@ void Compositor::checkUnredirect() // force is needed when the list of windows changes (e.g. a window goes away) void Compositor::checkUnredirect(bool force) { - if (!hasScene() || m_scene->overlayWindow()->window() == None || !options->isUnredirectFullscreen()) + if (!hasScene() || !m_scene->overlayWindow() || m_scene->overlayWindow()->window() == None || !options->isUnredirectFullscreen()) return; if (force) forceUnredirectCheck = true; @@ -716,7 +716,7 @@ void Compositor::checkUnredirect(bool force) void Compositor::delayedCheckUnredirect() { - if (!hasScene() || m_scene->overlayWindow()->window() == None || !(options->isUnredirectFullscreen() || sender() == options)) + if (!hasScene() || !m_scene->overlayWindow() || m_scene->overlayWindow()->window() == None || !(options->isUnredirectFullscreen() || sender() == options)) return; ToplevelList list; bool changed = forceUnredirectCheck; diff --git a/egl_wayland_backend.cpp b/egl_wayland_backend.cpp index 62f5f4d02f..9e436ece77 100644 --- a/egl_wayland_backend.cpp +++ b/egl_wayland_backend.cpp @@ -369,6 +369,11 @@ void EglWaylandBackend::lastFrameRendered() Compositor::self()->lastFrameRendered(); } +bool EglWaylandBackend::usesOverlayWindow() const +{ + return false; +} + /************************************************ * EglTexture ************************************************/ diff --git a/egl_wayland_backend.h b/egl_wayland_backend.h index 8712764ca6..c07d950ca1 100644 --- a/egl_wayland_backend.h +++ b/egl_wayland_backend.h @@ -69,6 +69,7 @@ public: virtual bool isLastFrameRendered() const override; Xcb::Shm *shm(); void lastFrameRendered(); + virtual bool usesOverlayWindow() const override; protected: virtual void present(); diff --git a/eglonxbackend.cpp b/eglonxbackend.cpp index 53442e2a9c..d4205d26a7 100644 --- a/eglonxbackend.cpp +++ b/eglonxbackend.cpp @@ -35,6 +35,7 @@ namespace KWin EglOnXBackend::EglOnXBackend() : OpenGLBackend() + , m_overlayWindow(new OverlayWindow()) , ctx(EGL_NO_CONTEXT) , surfaceHasSubPost(0) , m_bufferAge(0) @@ -46,6 +47,9 @@ EglOnXBackend::EglOnXBackend() EglOnXBackend::~EglOnXBackend() { + if (isFailed()) { + m_overlayWindow->destroy(); + } cleanupGL(); doneCurrent(); eglDestroyContext(dpy, ctx); @@ -55,6 +59,7 @@ EglOnXBackend::~EglOnXBackend() if (overlayWindow()->window()) { overlayWindow()->destroy(); } + delete m_overlayWindow; } static bool gs_tripleBufferUndetected = true; @@ -420,6 +425,16 @@ void EglOnXBackend::doneCurrent() eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } +bool EglOnXBackend::usesOverlayWindow() const +{ + return true; +} + +OverlayWindow* EglOnXBackend::overlayWindow() +{ + return m_overlayWindow; +} + /************************************************ * EglTexture ************************************************/ diff --git a/eglonxbackend.h b/eglonxbackend.h index 36d47005f6..6c85b1691f 100644 --- a/eglonxbackend.h +++ b/eglonxbackend.h @@ -38,6 +38,8 @@ public: virtual void endRenderingFrame(const QRegion &damage, const QRegion &damagedRegion); virtual bool makeCurrent() override; virtual void doneCurrent() override; + virtual OverlayWindow* overlayWindow() override; + virtual bool usesOverlayWindow() const override; protected: virtual void present(); @@ -46,6 +48,10 @@ private: void init(); bool initBufferConfigs(); bool initRenderingContext(); + /** + * @brief The OverlayWindow used by this Backend. + **/ + OverlayWindow *m_overlayWindow; EGLDisplay dpy; EGLConfig config; EGLSurface surface; diff --git a/glxbackend.cpp b/glxbackend.cpp index 73e9dfa186..e9cd430fc6 100644 --- a/glxbackend.cpp +++ b/glxbackend.cpp @@ -42,6 +42,7 @@ namespace KWin { GlxBackend::GlxBackend() : OpenGLBackend() + , m_overlayWindow(new OverlayWindow()) , window(None) , fbconfig(NULL) , glxWindow(None) @@ -54,6 +55,9 @@ GlxBackend::GlxBackend() GlxBackend::~GlxBackend() { + if (isFailed()) { + m_overlayWindow->destroy(); + } // TODO: cleanup in error case // do cleanup after initBuffer() cleanupGL(); @@ -70,6 +74,7 @@ GlxBackend::~GlxBackend() overlayWindow()->destroy(); checkGLError("Cleanup"); + delete m_overlayWindow; } static bool gs_tripleBufferUndetected = true; @@ -593,6 +598,16 @@ void GlxBackend::doneCurrent() glXMakeCurrent(display(), None, nullptr); } +OverlayWindow* GlxBackend::overlayWindow() +{ + return m_overlayWindow; +} + +bool GlxBackend::usesOverlayWindow() const +{ + return true; +} + /******************************************************** * GlxTexture *******************************************************/ diff --git a/glxbackend.h b/glxbackend.h index 26ca19c27c..d9f81ec426 100644 --- a/glxbackend.h +++ b/glxbackend.h @@ -48,6 +48,8 @@ public: virtual void endRenderingFrame(const QRegion &damage, const QRegion &damagedRegion); virtual bool makeCurrent() override; virtual void doneCurrent() override; + virtual OverlayWindow* overlayWindow() override; + virtual bool usesOverlayWindow() const override; protected: virtual void present(); @@ -61,6 +63,10 @@ private: bool initFbConfig(); void setSwapInterval(int interval); + /** + * @brief The OverlayWindow used by this Backend. + **/ + OverlayWindow *m_overlayWindow; Window window; FBConfigInfo fbcdrawableinfo[ 32 + 1 ]; GLXFBConfig fbconfig; diff --git a/scene.cpp b/scene.cpp index 333514de4a..d13e84b862 100644 --- a/scene.cpp +++ b/scene.cpp @@ -619,6 +619,9 @@ bool Scene::syncsToVBlank() const void Scene::screenGeometryChanged(const QSize &size) { + if (!overlayWindow()) { + return; + } overlayWindow()->resize(size); } diff --git a/scene.h b/scene.h index 1a0855f35d..09689c2da7 100644 --- a/scene.h +++ b/scene.h @@ -121,6 +121,10 @@ public: virtual bool makeOpenGLContextCurrent(); virtual void doneOpenGLContextCurrent(); + /** + * Whether the Scene uses an X11 overlay window to perform compositing. + */ + virtual bool usesOverlayWindow() const = 0; /** * @brief Allows the Compositor to delay the rendering of the next frame until the last one * has been rendered. This is mostly interesting in case that the system compositor is not able diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 6e113ef473..09079cd921 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -79,8 +79,7 @@ extern int currentRefreshRate(); // SceneOpenGL //**************************************** OpenGLBackend::OpenGLBackend() - : m_overlayWindow(new OverlayWindow()) // TODO: maybe create only if needed? - , m_syncsToVBlank(false) + : m_syncsToVBlank(false) , m_blocksForRetrace(false) , m_directRendering(false) , m_haveBufferAge(false) @@ -90,10 +89,6 @@ OpenGLBackend::OpenGLBackend() OpenGLBackend::~OpenGLBackend() { - if (isFailed()) { - m_overlayWindow->destroy(); - } - delete m_overlayWindow; } void OpenGLBackend::setFailed(const QString &reason) @@ -138,6 +133,11 @@ bool OpenGLBackend::isLastFrameRendered() const return true; } +OverlayWindow* OpenGLBackend::overlayWindow() +{ + return NULL; +} + /************************************************ * SceneOpenGL ***********************************************/ diff --git a/scene_opengl.h b/scene_opengl.h index 6d6a0ecc27..6b0fe600c9 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -52,6 +52,7 @@ public: virtual Shadow *createShadow(Toplevel *toplevel); virtual void screenGeometryChanged(const QSize &size); virtual OverlayWindow *overlayWindow(); + virtual bool usesOverlayWindow() const; virtual bool blocksForRetrace() const; virtual bool syncsToVBlank() const; virtual bool makeOpenGLContextCurrent() override; @@ -483,6 +484,7 @@ public: * frame got rendered. If a backend needs more control it needs to implement this method. */ virtual bool isLastFrameRendered() const; + virtual bool usesOverlayWindow() const = 0; /** * @brief Compositor is going into idle mode, flushes any pending paints. **/ @@ -504,9 +506,7 @@ public: * * @return :OverlayWindow* **/ - OverlayWindow *overlayWindow() { - return m_overlayWindow; - } + virtual OverlayWindow *overlayWindow(); /** * @brief Whether the creation of the Backend failed. * @@ -635,10 +635,6 @@ protected: SwapProfiler m_swapProfiler; private: - /** - * @brief The OverlayWindow used by this Backend. - **/ - OverlayWindow *m_overlayWindow; /** * @brief Whether VSync is available and used, defaults to @c false. **/ @@ -683,6 +679,11 @@ inline bool SceneOpenGL::isLastFrameRendered() const return m_backend->isLastFrameRendered(); } +inline bool SceneOpenGL::usesOverlayWindow() const +{ + return m_backend->usesOverlayWindow(); +} + inline SceneOpenGL::Texture* OpenGLWindowPixmap::texture() const { return m_texture.data(); diff --git a/scene_xrender.cpp b/scene_xrender.cpp index ecc0e6d583..6e3525b8db 100644 --- a/scene_xrender.cpp +++ b/scene_xrender.cpp @@ -243,6 +243,11 @@ void X11XRenderBackend::screenGeometryChanged(const QSize &size) init(false); } +bool X11XRenderBackend::usesOverlayWindow() const +{ + return true; +} + //**************************************** // SceneXrender //**************************************** diff --git a/scene_xrender.h b/scene_xrender.h index 59fdb550ab..d9e82a98f4 100644 --- a/scene_xrender.h +++ b/scene_xrender.h @@ -53,6 +53,7 @@ public: * @return :OverlayWindow* **/ virtual OverlayWindow *overlayWindow(); + virtual bool usesOverlayWindow() const = 0; /** * @brief Shows the Overlay Window * @@ -136,6 +137,7 @@ public: virtual OverlayWindow* overlayWindow(); virtual void showOverlay(); virtual void screenGeometryChanged(const QSize &size); + virtual bool usesOverlayWindow() const; private: void init(bool createOverlay); void createBuffer(); @@ -163,6 +165,9 @@ public: virtual OverlayWindow *overlayWindow() { return m_backend->overlayWindow(); } + virtual bool usesOverlayWindow() const { + return m_backend->usesOverlayWindow(); + } virtual bool isLastFrameRendered() const { return m_backend->isLastFrameRendered(); }