x11: Use global share context
This is needed to share window thumbnails between kwin's scene graph and qtquick.
This commit is contained in:
parent
8ed364337b
commit
172c541cad
6 changed files with 60 additions and 30 deletions
|
@ -29,8 +29,6 @@
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
||||||
static std::unique_ptr<QOpenGLContext> s_shareContext;
|
|
||||||
|
|
||||||
class Q_DECL_HIDDEN EffectQuickView::Private
|
class Q_DECL_HIDDEN EffectQuickView::Private
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -88,7 +86,7 @@ EffectQuickView::EffectQuickView(QObject *parent, ExportMode exportMode)
|
||||||
format.setStencilBufferSize(8);
|
format.setStencilBufferSize(8);
|
||||||
|
|
||||||
d->m_glcontext.reset(new QOpenGLContext);
|
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->setFormat(format);
|
||||||
d->m_glcontext->create();
|
d->m_glcontext->create();
|
||||||
|
|
||||||
|
@ -103,11 +101,6 @@ EffectQuickView::EffectQuickView(QObject *parent, ExportMode exportMode)
|
||||||
|
|
||||||
if (!d->m_glcontext->shareContext()) {
|
if (!d->m_glcontext->shareContext()) {
|
||||||
qCDebug(LIBKWINEFFECTS) << "Failed to create a shared context, falling back to raster rendering";
|
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
|
// still render via GL, but blit for presentation
|
||||||
d->m_useBlit = true;
|
d->m_useBlit = true;
|
||||||
}
|
}
|
||||||
|
@ -238,11 +231,6 @@ void EffectQuickView::forwardKeyEvent(QKeyEvent *keyEvent)
|
||||||
QCoreApplication::sendEvent(d->m_view, keyEvent);
|
QCoreApplication::sendEvent(d->m_view, keyEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectQuickView::setShareContext(std::unique_ptr<QOpenGLContext> context)
|
|
||||||
{
|
|
||||||
s_shareContext = std::move(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect EffectQuickView::geometry() const
|
QRect EffectQuickView::geometry() const
|
||||||
{
|
{
|
||||||
return d->m_view->geometry();
|
return d->m_view->geometry();
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
class QKeyEvent;
|
class QKeyEvent;
|
||||||
class QMouseEvent;
|
class QMouseEvent;
|
||||||
class QOpenGLContext;
|
|
||||||
|
|
||||||
class QMouseEvent;
|
class QMouseEvent;
|
||||||
class QKeyEvent;
|
class QKeyEvent;
|
||||||
|
@ -49,8 +48,6 @@ class KWINEFFECTS_EXPORT EffectQuickView : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void setShareContext(std::unique_ptr<QOpenGLContext> context);
|
|
||||||
|
|
||||||
enum class ExportMode {
|
enum class ExportMode {
|
||||||
/** The contents will be available as a texture in the shared contexts. Image will be blank*/
|
/** The contents will be available as a texture in the shared contexts. Image will be blank*/
|
||||||
Texture,
|
Texture,
|
||||||
|
|
|
@ -417,6 +417,15 @@ int main(int argc, char * argv[])
|
||||||
QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
|
QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
|
||||||
// KSMServer talks to us directly on DBus.
|
// KSMServer talks to us directly on DBus.
|
||||||
QCoreApplication::setAttribute(Qt::AA_DisableSessionManager);
|
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);
|
KWin::ApplicationX11 a(argc, argv);
|
||||||
a.setupTranslator();
|
a.setupTranslator();
|
||||||
|
@ -424,11 +433,6 @@ int main(int argc, char * argv[])
|
||||||
KWin::Application::createAboutData();
|
KWin::Application::createAboutData();
|
||||||
KQuickAddons::QtQuickSettings::init();
|
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"));
|
QCommandLineOption replaceOption(QStringLiteral("replace"), i18n("Replace already-running ICCCM2.0-compliant window manager"));
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "eglbackend.h"
|
#include "eglbackend.h"
|
||||||
|
#include "logging.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "overlaywindow.h"
|
#include "overlaywindow.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
@ -16,6 +17,9 @@
|
||||||
#include "surfaceitem_x11.h"
|
#include "surfaceitem_x11.h"
|
||||||
#include "x11_platform.h"
|
#include "x11_platform.h"
|
||||||
|
|
||||||
|
#include <QOpenGLContext>
|
||||||
|
#include <QtPlatformHeaders/QEGLNativeContext>
|
||||||
|
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -48,6 +52,30 @@ PlatformSurfaceTexture *EglBackend::createPlatformSurfaceTextureX11(SurfacePixma
|
||||||
return new EglSurfaceTextureX11(this, texture);
|
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)
|
void EglBackend::screenGeometryChanged(const QSize &size)
|
||||||
{
|
{
|
||||||
Q_UNUSED(size)
|
Q_UNUSED(size)
|
||||||
|
|
|
@ -27,6 +27,8 @@ public:
|
||||||
EglBackend(Display *display, X11StandalonePlatform *platform);
|
EglBackend(Display *display, X11StandalonePlatform *platform);
|
||||||
~EglBackend() override;
|
~EglBackend() override;
|
||||||
|
|
||||||
|
void init() override;
|
||||||
|
|
||||||
PlatformSurfaceTexture *createPlatformSurfaceTextureX11(SurfacePixmapX11 *texture) override;
|
PlatformSurfaceTexture *createPlatformSurfaceTextureX11(SurfacePixmapX11 *texture) override;
|
||||||
QRegion beginFrame(int screenId) override;
|
QRegion beginFrame(int screenId) override;
|
||||||
void endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion) override;
|
void endFrame(int screenId, const QRegion &damage, const QRegion &damagedRegion) override;
|
||||||
|
|
|
@ -129,7 +129,6 @@ GlxBackend::~GlxBackend()
|
||||||
// do cleanup after initBuffer()
|
// do cleanup after initBuffer()
|
||||||
cleanupGL();
|
cleanupGL();
|
||||||
doneCurrent();
|
doneCurrent();
|
||||||
EffectQuickView::setShareContext(nullptr);
|
|
||||||
|
|
||||||
if (ctx)
|
if (ctx)
|
||||||
glXDestroyContext(display(), ctx);
|
glXDestroyContext(display(), ctx);
|
||||||
|
@ -311,6 +310,24 @@ bool GlxBackend::initRenderingContext()
|
||||||
{
|
{
|
||||||
const bool direct = true;
|
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
|
// Use glXCreateContextAttribsARB() when it's available
|
||||||
if (hasExtension(QByteArrayLiteral("GLX_ARB_create_context"))) {
|
if (hasExtension(QByteArrayLiteral("GLX_ARB_create_context"))) {
|
||||||
const bool have_robustness = hasExtension(QByteArrayLiteral("GLX_ARB_create_context_robustness"));
|
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++) {
|
for (auto it = candidates.begin(); it != candidates.end(); it++) {
|
||||||
const auto attribs = it->build();
|
const auto attribs = it->build();
|
||||||
ctx = glXCreateContextAttribsARB(display(), fbconfig, nullptr, true, attribs.data());
|
ctx = glXCreateContextAttribsARB(display(), fbconfig, globalShareContext, true, attribs.data());
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
qCDebug(KWIN_X11STANDALONE) << "Created GLX context with attributes:" << &(*it);
|
qCDebug(KWIN_X11STANDALONE) << "Created GLX context with attributes:" << &(*it);
|
||||||
break;
|
break;
|
||||||
|
@ -361,7 +378,7 @@ bool GlxBackend::initRenderingContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
ctx = glXCreateNewContext(display(), fbconfig, GLX_RGBA_TYPE, nullptr, direct);
|
ctx = glXCreateNewContext(display(), fbconfig, GLX_RGBA_TYPE, globalShareContext, direct);
|
||||||
|
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
qCDebug(KWIN_X11STANDALONE) << "Failed to create an OpenGL context.";
|
qCDebug(KWIN_X11STANDALONE) << "Failed to create an OpenGL context.";
|
||||||
|
@ -375,12 +392,6 @@ bool GlxBackend::initRenderingContext()
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue