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;