Allow using EGLOnXBackend with X11WindowedBackend
Mostly refactoring to not take the global X11 information (connection, display, etc.). Adds a dedicated ctor overload which takes the X11WindowedBackend. SceneOpenGL is adjusted to create an EGLOnXBackend instead of Wayland one if the X11WindowedBackend is used.
This commit is contained in:
parent
3cc1032839
commit
a1642a85d3
5 changed files with 105 additions and 26 deletions
|
@ -19,9 +19,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
#include "eglonxbackend.h"
|
#include "eglonxbackend.h"
|
||||||
// kwin
|
// kwin
|
||||||
|
#include "main.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "overlaywindow.h"
|
#include "overlaywindow.h"
|
||||||
|
#include "screens.h"
|
||||||
#include "xcbutils.h"
|
#include "xcbutils.h"
|
||||||
|
#if HAVE_X11_XCB
|
||||||
|
#include "x11windowed_backend.h"
|
||||||
|
#endif
|
||||||
// kwin libs
|
// kwin libs
|
||||||
#include <kwinglplatform.h>
|
#include <kwinglplatform.h>
|
||||||
// Qt
|
// Qt
|
||||||
|
@ -33,23 +38,47 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
||||||
extern int screen_number; // main.cpp
|
|
||||||
|
|
||||||
EglOnXBackend::EglOnXBackend()
|
EglOnXBackend::EglOnXBackend()
|
||||||
: OpenGLBackend()
|
: OpenGLBackend()
|
||||||
, m_overlayWindow(new OverlayWindow())
|
, m_overlayWindow(new OverlayWindow())
|
||||||
, ctx(EGL_NO_CONTEXT)
|
, ctx(EGL_NO_CONTEXT)
|
||||||
, surfaceHasSubPost(0)
|
, surfaceHasSubPost(0)
|
||||||
, m_bufferAge(0)
|
, m_bufferAge(0)
|
||||||
|
, m_usesOverlayWindow(true)
|
||||||
|
, m_connection(connection())
|
||||||
|
, m_x11Display(display())
|
||||||
|
, m_rootWindow(rootWindow())
|
||||||
|
, m_x11ScreenNumber(kwinApp()->x11ScreenNumber())
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
// Egl is always direct rendering
|
// Egl is always direct rendering
|
||||||
setIsDirectRendering(true);
|
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()
|
EglOnXBackend::~EglOnXBackend()
|
||||||
{
|
{
|
||||||
if (isFailed()) {
|
if (isFailed() && m_overlayWindow) {
|
||||||
m_overlayWindow->destroy();
|
m_overlayWindow->destroy();
|
||||||
}
|
}
|
||||||
cleanupGL();
|
cleanupGL();
|
||||||
|
@ -58,10 +87,12 @@ EglOnXBackend::~EglOnXBackend()
|
||||||
eglDestroySurface(dpy, surface);
|
eglDestroySurface(dpy, surface);
|
||||||
eglTerminate(dpy);
|
eglTerminate(dpy);
|
||||||
eglReleaseThread();
|
eglReleaseThread();
|
||||||
if (overlayWindow()->window()) {
|
if (m_overlayWindow) {
|
||||||
overlayWindow()->destroy();
|
if (overlayWindow()->window()) {
|
||||||
|
overlayWindow()->destroy();
|
||||||
|
}
|
||||||
|
delete m_overlayWindow;
|
||||||
}
|
}
|
||||||
delete m_overlayWindow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gs_tripleBufferUndetected = true;
|
static bool gs_tripleBufferUndetected = true;
|
||||||
|
@ -178,13 +209,13 @@ bool EglOnXBackend::initRenderingContext()
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const int attribs[] = {
|
const int attribs[] = {
|
||||||
EGL_PLATFORM_X11_SCREEN_EXT, screen_number,
|
EGL_PLATFORM_X11_SCREEN_EXT, m_x11ScreenNumber,
|
||||||
EGL_NONE
|
EGL_NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
dpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT, display(), attribs);
|
dpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT, m_x11Display, attribs);
|
||||||
} else {
|
} else {
|
||||||
dpy = eglGetDisplay(display());
|
dpy = eglGetDisplay(m_x11Display);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dpy == EGL_NO_DISPLAY)
|
if (dpy == EGL_NO_DISPLAY)
|
||||||
|
@ -205,11 +236,26 @@ bool EglOnXBackend::initRenderingContext()
|
||||||
|
|
||||||
initBufferConfigs();
|
initBufferConfigs();
|
||||||
|
|
||||||
if (!overlayWindow()->create()) {
|
if (m_usesOverlayWindow) {
|
||||||
qCCritical(KWIN_CORE) << "Could not get overlay window";
|
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;
|
return false;
|
||||||
} else {
|
|
||||||
overlayWindow()->setup(None);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (havePlatformBase) {
|
if (havePlatformBase) {
|
||||||
|
@ -217,10 +263,9 @@ bool EglOnXBackend::initRenderingContext()
|
||||||
// always 32 bits. eglCreatePlatformWindowSurfaceEXT() expects the
|
// always 32 bits. eglCreatePlatformWindowSurfaceEXT() expects the
|
||||||
// native_window parameter to be pointer to a Window, so this variable
|
// native_window parameter to be pointer to a Window, so this variable
|
||||||
// cannot be an xcb_window_t.
|
// cannot be an xcb_window_t.
|
||||||
const Window window = overlayWindow()->window();
|
|
||||||
surface = eglCreatePlatformWindowSurfaceEXT(dpy, config, (void *) &window, nullptr);
|
surface = eglCreatePlatformWindowSurfaceEXT(dpy, config, (void *) &window, nullptr);
|
||||||
} else {
|
} else {
|
||||||
surface = eglCreateWindowSurface(dpy, config, overlayWindow()->window(), nullptr);
|
surface = eglCreateWindowSurface(dpy, config, window, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef KWIN_HAVE_OPENGLES
|
#ifdef KWIN_HAVE_OPENGLES
|
||||||
|
@ -297,7 +342,9 @@ bool EglOnXBackend::initBufferConfigs()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Xcb::WindowAttributes attribs(rootWindow());
|
ScopedCPointer<xcb_get_window_attributes_reply_t> attribs(xcb_get_window_attributes_reply(m_connection,
|
||||||
|
xcb_get_window_attributes_unchecked(m_connection, m_rootWindow),
|
||||||
|
nullptr));
|
||||||
if (!attribs) {
|
if (!attribs) {
|
||||||
qCCritical(KWIN_CORE) << "Failed to get window attributes of root window";
|
qCCritical(KWIN_CORE) << "Failed to get window attributes of root window";
|
||||||
return false;
|
return false;
|
||||||
|
@ -322,7 +369,8 @@ void EglOnXBackend::present()
|
||||||
if (lastDamage().isEmpty())
|
if (lastDamage().isEmpty())
|
||||||
return;
|
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);
|
const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion);
|
||||||
|
|
||||||
if (fullRepaint || !surfaceHasSubPost) {
|
if (fullRepaint || !surfaceHasSubPost) {
|
||||||
|
@ -357,14 +405,14 @@ void EglOnXBackend::present()
|
||||||
} else {
|
} else {
|
||||||
// a part of the screen changed, and we can use eglPostSubBufferNV to copy the updated area
|
// a part of the screen changed, and we can use eglPostSubBufferNV to copy the updated area
|
||||||
foreach (const QRect & r, lastDamage().rects()) {
|
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());
|
setLastDamage(QRegion());
|
||||||
if (!supportsBufferAge()) {
|
if (!supportsBufferAge()) {
|
||||||
eglWaitGL();
|
eglWaitGL();
|
||||||
xcb_flush(connection());
|
xcb_flush(m_connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,7 +486,7 @@ void EglOnXBackend::endRenderingFrame(const QRegion &renderedRegion, const QRegi
|
||||||
glFlush();
|
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
|
overlayWindow()->show(); // since that pass may take long
|
||||||
|
|
||||||
// Save the damaged region to history
|
// Save the damaged region to history
|
||||||
|
@ -463,7 +511,7 @@ void EglOnXBackend::doneCurrent()
|
||||||
|
|
||||||
bool EglOnXBackend::usesOverlayWindow() const
|
bool EglOnXBackend::usesOverlayWindow() const
|
||||||
{
|
{
|
||||||
return true;
|
return m_usesOverlayWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayWindow* EglOnXBackend::overlayWindow()
|
OverlayWindow* EglOnXBackend::overlayWindow()
|
||||||
|
|
|
@ -24,6 +24,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class X11WindowedBackend;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief OpenGL Backend using Egl windowing system over an X overlay window.
|
* @brief OpenGL Backend using Egl windowing system over an X overlay window.
|
||||||
**/
|
**/
|
||||||
|
@ -31,6 +33,9 @@ class EglOnXBackend : public OpenGLBackend
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EglOnXBackend();
|
EglOnXBackend();
|
||||||
|
#if HAVE_X11_XCB
|
||||||
|
explicit EglOnXBackend(X11WindowedBackend *backend);
|
||||||
|
#endif
|
||||||
virtual ~EglOnXBackend();
|
virtual ~EglOnXBackend();
|
||||||
virtual void screenGeometryChanged(const QSize &size);
|
virtual void screenGeometryChanged(const QSize &size);
|
||||||
virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture);
|
virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture);
|
||||||
|
@ -58,6 +63,14 @@ private:
|
||||||
EGLContext ctx;
|
EGLContext ctx;
|
||||||
int surfaceHasSubPost;
|
int surfaceHasSubPost;
|
||||||
int m_bufferAge;
|
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;
|
friend class EglTexture;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
// for Wayland
|
// for Wayland
|
||||||
#if HAVE_WAYLAND_EGL
|
#if HAVE_WAYLAND_EGL
|
||||||
#include "egl_wayland_backend.h"
|
#include "egl_wayland_backend.h"
|
||||||
|
#include "wayland_backend.h"
|
||||||
|
#endif
|
||||||
|
#if HAVE_X11_XCB
|
||||||
|
#include "x11windowed_backend.h"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifndef KWIN_HAVE_OPENGLES
|
#ifndef KWIN_HAVE_OPENGLES
|
||||||
|
@ -483,15 +487,20 @@ SceneOpenGL *SceneOpenGL::createScene(QObject *parent)
|
||||||
break;
|
break;
|
||||||
case EglPlatformInterface:
|
case EglPlatformInterface:
|
||||||
#ifdef KWIN_HAVE_EGL
|
#ifdef KWIN_HAVE_EGL
|
||||||
#if HAVE_WAYLAND_EGL
|
|
||||||
if (kwinApp()->shouldUseWaylandForCompositing()) {
|
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 {
|
} else {
|
||||||
backend = new EglOnXBackend();
|
backend = new EglOnXBackend();
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
backend = new EglOnXBackend();
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -294,4 +294,12 @@ void X11WindowedBackend::installCursorFromServer()
|
||||||
// TODO: unset cursor
|
// TODO: unset cursor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xcb_window_t X11WindowedBackend::rootWindow() const
|
||||||
|
{
|
||||||
|
if (!m_screen) {
|
||||||
|
return XCB_WINDOW_NONE;
|
||||||
|
}
|
||||||
|
return m_screen->root;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ public:
|
||||||
Display *display() const {
|
Display *display() const {
|
||||||
return m_display;
|
return m_display;
|
||||||
}
|
}
|
||||||
|
xcb_window_t rootWindow() const;
|
||||||
|
|
||||||
bool isValid() const {
|
bool isValid() const {
|
||||||
return m_connection != nullptr && m_window != XCB_WINDOW_NONE;
|
return m_connection != nullptr && m_window != XCB_WINDOW_NONE;
|
||||||
|
|
Loading…
Reference in a new issue