x11: Use global share context

This is needed to share window thumbnails between kwin's scene graph and
qtquick.
This commit is contained in:
Vlad Zahorodnii 2021-06-03 09:24:52 +03:00
parent 8ed364337b
commit 172c541cad
6 changed files with 60 additions and 30 deletions

View file

@ -29,8 +29,6 @@
namespace KWin
{
static std::unique_ptr<QOpenGLContext> s_shareContext;
class Q_DECL_HIDDEN EffectQuickView::Private
{
public:
@ -88,7 +86,7 @@ EffectQuickView::EffectQuickView(QObject *parent, ExportMode exportMode)
format.setStencilBufferSize(8);
d->m_glcontext.reset(new QOpenGLContext);
d->m_glcontext->setShareContext(s_shareContext.get());
d->m_glcontext->setShareContext(QOpenGLContext::globalShareContext());
d->m_glcontext->setFormat(format);
d->m_glcontext->create();
@ -103,11 +101,6 @@ EffectQuickView::EffectQuickView(QObject *parent, ExportMode exportMode)
if (!d->m_glcontext->shareContext()) {
qCDebug(LIBKWINEFFECTS) << "Failed to create a shared context, falling back to raster rendering";
qCDebug(LIBKWINEFFECTS) << "Extra debug:";
qCDebug(LIBKWINEFFECTS) << "our context:" << d->m_glcontext.data();
qCDebug(LIBKWINEFFECTS) << "share context:" << s_shareContext.get();
// still render via GL, but blit for presentation
d->m_useBlit = true;
}
@ -238,11 +231,6 @@ void EffectQuickView::forwardKeyEvent(QKeyEvent *keyEvent)
QCoreApplication::sendEvent(d->m_view, keyEvent);
}
void EffectQuickView::setShareContext(std::unique_ptr<QOpenGLContext> context)
{
s_shareContext = std::move(context);
}
QRect EffectQuickView::geometry() const
{
return d->m_view->geometry();

View file

@ -21,7 +21,6 @@
class QKeyEvent;
class QMouseEvent;
class QOpenGLContext;
class QMouseEvent;
class QKeyEvent;
@ -49,8 +48,6 @@ class KWINEFFECTS_EXPORT EffectQuickView : public QObject
Q_OBJECT
public:
static void setShareContext(std::unique_ptr<QOpenGLContext> context);
enum class ExportMode {
/** The contents will be available as a texture in the shared contexts. Image will be blank*/
Texture,

View file

@ -417,6 +417,15 @@ int main(int argc, char * argv[])
QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
// KSMServer talks to us directly on DBus.
QCoreApplication::setAttribute(Qt::AA_DisableSessionManager);
// For sharing thumbnails between our scene graph and qtquick.
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
// shared opengl contexts must have the same reset notification policy
format.setOptions(QSurfaceFormat::ResetNotification);
// disables vsync for any QtQuick windows we create (BUG 406180)
format.setSwapInterval(0);
QSurfaceFormat::setDefaultFormat(format);
KWin::ApplicationX11 a(argc, argv);
a.setupTranslator();
@ -424,11 +433,6 @@ int main(int argc, char * argv[])
KWin::Application::createAboutData();
KQuickAddons::QtQuickSettings::init();
// disables vsync for any QtQuick windows we create (BUG 406180)
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
format.setSwapInterval(0);
QSurfaceFormat::setDefaultFormat(format);
QCommandLineOption replaceOption(QStringLiteral("replace"), i18n("Replace already-running ICCCM2.0-compliant window manager"));
QCommandLineParser parser;

View file

@ -6,6 +6,7 @@
*/
#include "eglbackend.h"
#include "logging.h"
#include "options.h"
#include "overlaywindow.h"
#include "platform.h"
@ -16,6 +17,9 @@
#include "surfaceitem_x11.h"
#include "x11_platform.h"
#include <QOpenGLContext>
#include <QtPlatformHeaders/QEGLNativeContext>
namespace KWin
{
@ -48,6 +52,30 @@ PlatformSurfaceTexture *EglBackend::createPlatformSurfaceTextureX11(SurfacePixma
return new EglSurfaceTextureX11(this, texture);
}
void EglBackend::init()
{
QOpenGLContext *qtShareContext = QOpenGLContext::globalShareContext();
EGLContext shareContext = EGL_NO_CONTEXT;
if (qtShareContext) {
qDebug(KWIN_X11STANDALONE) << "Global share context format:" << qtShareContext->format();
const QVariant nativeHandle = qtShareContext->nativeHandle();
if (!nativeHandle.canConvert<QEGLNativeContext>()) {
setFailed(QStringLiteral("Invalid QOpenGLContext::globalShareContext()"));
return;
} else {
QEGLNativeContext handle = qvariant_cast<QEGLNativeContext>(nativeHandle);
shareContext = handle.context();
}
}
if (shareContext == EGL_NO_CONTEXT) {
setFailed(QStringLiteral("QOpenGLContext::globalShareContext() is required"));
return;
}
kwinApp()->platform()->setSceneEglGlobalShareContext(shareContext);
EglOnXBackend::init();
}
void EglBackend::screenGeometryChanged(const QSize &size)
{
Q_UNUSED(size)

View file

@ -27,6 +27,8 @@ public:
EglBackend(Display *display, X11StandalonePlatform *platform);
~EglBackend() override;
void init() override;
PlatformSurfaceTexture *createPlatformSurfaceTextureX11(SurfacePixmapX11 *texture) override;
QRegion beginFrame(int screenId) override;
void endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion) override;

View file

@ -129,7 +129,6 @@ GlxBackend::~GlxBackend()
// do cleanup after initBuffer()
cleanupGL();
doneCurrent();
EffectQuickView::setShareContext(nullptr);
if (ctx)
glXDestroyContext(display(), ctx);
@ -311,6 +310,24 @@ bool GlxBackend::initRenderingContext()
{
const bool direct = true;
QOpenGLContext *qtGlobalShareContext = QOpenGLContext::globalShareContext();
GLXContext globalShareContext = nullptr;
if (qtGlobalShareContext) {
qDebug(KWIN_X11STANDALONE) << "Global share context format:" << qtGlobalShareContext->format();
const QVariant nativeHandle = qtGlobalShareContext->nativeHandle();
if (!nativeHandle.canConvert<QGLXNativeContext>()) {
qCDebug(KWIN_X11STANDALONE) << "Invalid QOpenGLContext::globalShareContext()";
return false;
} else {
QGLXNativeContext handle = qvariant_cast<QGLXNativeContext>(nativeHandle);
globalShareContext = handle.context();
}
}
if (!globalShareContext) {
qCWarning(KWIN_X11STANDALONE) << "QOpenGLContext::globalShareContext() is required";
return false;
}
// Use glXCreateContextAttribsARB() when it's available
if (hasExtension(QByteArrayLiteral("GLX_ARB_create_context"))) {
const bool have_robustness = hasExtension(QByteArrayLiteral("GLX_ARB_create_context_robustness"));
@ -352,7 +369,7 @@ bool GlxBackend::initRenderingContext()
}
for (auto it = candidates.begin(); it != candidates.end(); it++) {
const auto attribs = it->build();
ctx = glXCreateContextAttribsARB(display(), fbconfig, nullptr, true, attribs.data());
ctx = glXCreateContextAttribsARB(display(), fbconfig, globalShareContext, true, attribs.data());
if (ctx) {
qCDebug(KWIN_X11STANDALONE) << "Created GLX context with attributes:" << &(*it);
break;
@ -361,7 +378,7 @@ bool GlxBackend::initRenderingContext()
}
if (!ctx)
ctx = glXCreateNewContext(display(), fbconfig, GLX_RGBA_TYPE, nullptr, direct);
ctx = glXCreateNewContext(display(), fbconfig, GLX_RGBA_TYPE, globalShareContext, direct);
if (!ctx) {
qCDebug(KWIN_X11STANDALONE) << "Failed to create an OpenGL context.";
@ -375,12 +392,6 @@ bool GlxBackend::initRenderingContext()
return false;
}
auto qtContext = new QOpenGLContext;
QGLXNativeContext native(ctx, display());
qtContext->setNativeHandle(QVariant::fromValue(native));
qtContext->create();
EffectQuickView::setShareContext(std::unique_ptr<QOpenGLContext>(qtContext));
return true;
}