diff --git a/eglonxbackend.cpp b/eglonxbackend.cpp index f4b11dab08..951f5baca6 100644 --- a/eglonxbackend.cpp +++ b/eglonxbackend.cpp @@ -19,9 +19,14 @@ along with this program. If not, see . *********************************************************************/ #include "eglonxbackend.h" // kwin +#include "main.h" #include "options.h" #include "overlaywindow.h" +#include "screens.h" #include "xcbutils.h" +#if HAVE_X11_XCB +#include "x11windowed_backend.h" +#endif // kwin libs #include // Qt @@ -33,23 +38,47 @@ along with this program. If not, see . namespace KWin { -extern int screen_number; // main.cpp - EglOnXBackend::EglOnXBackend() : OpenGLBackend() , m_overlayWindow(new OverlayWindow()) , ctx(EGL_NO_CONTEXT) , surfaceHasSubPost(0) , m_bufferAge(0) + , m_usesOverlayWindow(true) + , m_connection(connection()) + , m_x11Display(display()) + , m_rootWindow(rootWindow()) + , m_x11ScreenNumber(kwinApp()->x11ScreenNumber()) { init(); // Egl is always direct rendering setIsDirectRendering(true); } +#if HAVE_X11_XCB +EglOnXBackend::EglOnXBackend(X11WindowedBackend *backend) + : OpenGLBackend() + , m_overlayWindow(nullptr) + , ctx(EGL_NO_CONTEXT) + , surfaceHasSubPost(0) + , m_bufferAge(0) + , m_usesOverlayWindow(false) + , m_x11Backend(backend) + , m_connection(backend->connection()) + , m_x11Display(backend->display()) + , m_rootWindow(backend->rootWindow()) + , m_x11ScreenNumber(backend->screenNumer()) +{ + init(); + // Egl is always direct rendering + setIsDirectRendering(true); +} +#endif + + EglOnXBackend::~EglOnXBackend() { - if (isFailed()) { + if (isFailed() && m_overlayWindow) { m_overlayWindow->destroy(); } cleanupGL(); @@ -58,10 +87,12 @@ EglOnXBackend::~EglOnXBackend() eglDestroySurface(dpy, surface); eglTerminate(dpy); eglReleaseThread(); - if (overlayWindow()->window()) { - overlayWindow()->destroy(); + if (m_overlayWindow) { + if (overlayWindow()->window()) { + overlayWindow()->destroy(); + } + delete m_overlayWindow; } - delete m_overlayWindow; } static bool gs_tripleBufferUndetected = true; @@ -178,13 +209,13 @@ bool EglOnXBackend::initRenderingContext() return false; const int attribs[] = { - EGL_PLATFORM_X11_SCREEN_EXT, screen_number, + EGL_PLATFORM_X11_SCREEN_EXT, m_x11ScreenNumber, EGL_NONE }; - dpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT, display(), attribs); + dpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT, m_x11Display, attribs); } else { - dpy = eglGetDisplay(display()); + dpy = eglGetDisplay(m_x11Display); } if (dpy == EGL_NO_DISPLAY) @@ -205,11 +236,26 @@ bool EglOnXBackend::initRenderingContext() initBufferConfigs(); - if (!overlayWindow()->create()) { - qCCritical(KWIN_CORE) << "Could not get overlay window"; + if (m_usesOverlayWindow) { + if (!overlayWindow()->create()) { + qCCritical(KWIN_CORE) << "Could not get overlay window"; + return false; + } else { + overlayWindow()->setup(None); + } + } + + xcb_window_t window = XCB_WINDOW_NONE; + if (m_overlayWindow) { + window = m_overlayWindow->window(); + } +#if HAVE_X11_XCB + else if (m_x11Backend) { + window = m_x11Backend->window(); + } +#endif + if (window == XCB_WINDOW_NONE) { return false; - } else { - overlayWindow()->setup(None); } if (havePlatformBase) { @@ -217,10 +263,9 @@ bool EglOnXBackend::initRenderingContext() // always 32 bits. eglCreatePlatformWindowSurfaceEXT() expects the // native_window parameter to be pointer to a Window, so this variable // cannot be an xcb_window_t. - const Window window = overlayWindow()->window(); surface = eglCreatePlatformWindowSurfaceEXT(dpy, config, (void *) &window, nullptr); } else { - surface = eglCreateWindowSurface(dpy, config, overlayWindow()->window(), nullptr); + surface = eglCreateWindowSurface(dpy, config, window, nullptr); } #ifdef KWIN_HAVE_OPENGLES @@ -297,7 +342,9 @@ bool EglOnXBackend::initBufferConfigs() return false; } - Xcb::WindowAttributes attribs(rootWindow()); + ScopedCPointer attribs(xcb_get_window_attributes_reply(m_connection, + xcb_get_window_attributes_unchecked(m_connection, m_rootWindow), + nullptr)); if (!attribs) { qCCritical(KWIN_CORE) << "Failed to get window attributes of root window"; return false; @@ -322,7 +369,8 @@ void EglOnXBackend::present() if (lastDamage().isEmpty()) return; - const QRegion displayRegion(0, 0, displayWidth(), displayHeight()); + const QSize screenSize = screens()->size(); + const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height()); const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion); if (fullRepaint || !surfaceHasSubPost) { @@ -357,14 +405,14 @@ void EglOnXBackend::present() } else { // a part of the screen changed, and we can use eglPostSubBufferNV to copy the updated area foreach (const QRect & r, lastDamage().rects()) { - eglPostSubBufferNV(dpy, surface, r.left(), displayHeight() - r.bottom() - 1, r.width(), r.height()); + eglPostSubBufferNV(dpy, surface, r.left(), screenSize.height() - r.bottom() - 1, r.width(), r.height()); } } setLastDamage(QRegion()); if (!supportsBufferAge()) { eglWaitGL(); - xcb_flush(connection()); + xcb_flush(m_connection); } } @@ -438,7 +486,7 @@ void EglOnXBackend::endRenderingFrame(const QRegion &renderedRegion, const QRegi glFlush(); } - if (overlayWindow()->window()) // show the window only after the first pass, + if (m_overlayWindow && overlayWindow()->window()) // show the window only after the first pass, overlayWindow()->show(); // since that pass may take long // Save the damaged region to history @@ -463,7 +511,7 @@ void EglOnXBackend::doneCurrent() bool EglOnXBackend::usesOverlayWindow() const { - return true; + return m_usesOverlayWindow; } OverlayWindow* EglOnXBackend::overlayWindow() diff --git a/eglonxbackend.h b/eglonxbackend.h index 62eb30d3d0..b3aa0fcf76 100644 --- a/eglonxbackend.h +++ b/eglonxbackend.h @@ -24,6 +24,8 @@ along with this program. If not, see . namespace KWin { +class X11WindowedBackend; + /** * @brief OpenGL Backend using Egl windowing system over an X overlay window. **/ @@ -31,6 +33,9 @@ class EglOnXBackend : public OpenGLBackend { public: EglOnXBackend(); +#if HAVE_X11_XCB + explicit EglOnXBackend(X11WindowedBackend *backend); +#endif virtual ~EglOnXBackend(); virtual void screenGeometryChanged(const QSize &size); virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture); @@ -58,6 +63,14 @@ private: EGLContext ctx; int surfaceHasSubPost; int m_bufferAge; + bool m_usesOverlayWindow; +#if HAVE_X11_XCB + X11WindowedBackend *m_x11Backend = nullptr; +#endif + xcb_connection_t *m_connection; + Display *m_x11Display; + xcb_window_t m_rootWindow; + int m_x11ScreenNumber; friend class EglTexture; }; diff --git a/scene_opengl.cpp b/scene_opengl.cpp index f1033c237d..30b113dfd0 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -32,6 +32,10 @@ along with this program. If not, see . // for Wayland #if HAVE_WAYLAND_EGL #include "egl_wayland_backend.h" +#include "wayland_backend.h" +#endif +#if HAVE_X11_XCB +#include "x11windowed_backend.h" #endif #endif #ifndef KWIN_HAVE_OPENGLES @@ -483,15 +487,20 @@ SceneOpenGL *SceneOpenGL::createScene(QObject *parent) break; case EglPlatformInterface: #ifdef KWIN_HAVE_EGL -#if HAVE_WAYLAND_EGL if (kwinApp()->shouldUseWaylandForCompositing()) { - backend = new EglWaylandBackend(); +#if HAVE_WAYLAND_EGL + if (Wayland::WaylandBackend::self()) { + backend = new EglWaylandBackend(); + } +#endif +#if HAVE_X11_XCB + if (!backend && X11WindowedBackend::self()) { + backend = new EglOnXBackend(X11WindowedBackend::self()); + } +#endif } else { backend = new EglOnXBackend(); } -#else - backend = new EglOnXBackend(); -#endif #endif break; default: diff --git a/x11windowed_backend.cpp b/x11windowed_backend.cpp index b21cdbf3c5..d9f6ed3209 100644 --- a/x11windowed_backend.cpp +++ b/x11windowed_backend.cpp @@ -294,4 +294,12 @@ void X11WindowedBackend::installCursorFromServer() // TODO: unset cursor } +xcb_window_t X11WindowedBackend::rootWindow() const +{ + if (!m_screen) { + return XCB_WINDOW_NONE; + } + return m_screen->root; +} + } diff --git a/x11windowed_backend.h b/x11windowed_backend.h index dcf07000a0..e93235d16a 100644 --- a/x11windowed_backend.h +++ b/x11windowed_backend.h @@ -52,6 +52,7 @@ public: Display *display() const { return m_display; } + xcb_window_t rootWindow() const; bool isValid() const { return m_connection != nullptr && m_window != XCB_WINDOW_NONE;