diff options
Diffstat (limited to 'src')
12 files changed, 257 insertions, 35 deletions
diff --git a/src/platformheaders/nativecontexts/nativecontexts.pri b/src/platformheaders/nativecontexts/nativecontexts.pri index dcbeae2b0f..3fe62ea6fe 100644 --- a/src/platformheaders/nativecontexts/nativecontexts.pri +++ b/src/platformheaders/nativecontexts/nativecontexts.pri @@ -1 +1,2 @@ -HEADERS += $$PWD/qglxnativecontext.h +HEADERS += $$PWD/qglxnativecontext.h \ + $$PWD/qeglnativecontext.h diff --git a/src/platformheaders/nativecontexts/qeglnativecontext.h b/src/platformheaders/nativecontexts/qeglnativecontext.h new file mode 100644 index 0000000000..7028d81347 --- /dev/null +++ b/src/platformheaders/nativecontexts/qeglnativecontext.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLNATIVECONTEXT_H +#define QEGLNATIVECONTEXT_H + +#include <EGL/egl.h> + +QT_BEGIN_NAMESPACE + +struct QEGLNativeContext +{ + QEGLNativeContext() + : m_context(0), + m_display(0) + { } + + QEGLNativeContext(EGLContext ctx, EGLDisplay dpy) + : m_context(ctx), + m_display(dpy) + { } + + EGLContext context() const { return m_context; } + EGLDisplay display() const { return m_display; } + +private: + EGLContext m_context; + EGLDisplay m_display; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QEGLNativeContext) + +#endif // QEGLNATIVECONTEXT_H diff --git a/src/platformheaders/nativecontexts/qeglnativecontext.qdoc b/src/platformheaders/nativecontexts/qeglnativecontext.qdoc new file mode 100644 index 0000000000..62b1a5482e --- /dev/null +++ b/src/platformheaders/nativecontexts/qeglnativecontext.qdoc @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QEGLNativeContext + \inmodule QtPlatformHeaders + \since 5.4 + + \brief A class encapsulating an EGL context and display handle + + \note As of Qt 5.4 there is no binary compatibility guarantee for this class, meaning + that an application using it is only guaranteed to work with the Qt version it was + developed against. + + \sa QOpenGLContext::setNativeHandle(), QOpenGLContext::nativeHandle() + */ + +/*! + \fn EGLContext QEGLNativeContext::context() const + + \return the EGL context. + */ + +/*! + \fn EGLDisplay QEGLNativeContext::display() const + + \return the EGL display. + */ + +/*! + \fn QEGLNativeContext::QEGLNativeContext() + + Construct a new instance with no handles. + */ + +/*! + \fn QEGLNativeContext::QEGLNativeContext(EGLContext ctx, EGLDisplay dpy) + + Constructs a new instance with the provided \a ctx and \a dpy handles. + */ diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index eec6463c21..9691d12682 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -44,6 +44,7 @@ #include "qeglpbuffer_p.h" #include <qpa/qplatformwindow.h> #include <QOpenGLContext> +#include <QtPlatformHeaders/QEGLNativeContext> #include <QDebug> QT_BEGIN_NAMESPACE @@ -108,25 +109,21 @@ QT_BEGIN_NAMESPACE #define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 #endif -QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display) - : m_eglDisplay(display) - , m_eglConfig(q_configFromGLFormat(display, format)) - , m_swapInterval(-1) - , m_swapIntervalEnvChecked(false) - , m_swapIntervalFromEnv(-1) -{ - init(format, share); -} - QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLConfig config) + EGLConfig *config, const QVariant &nativeHandle) : m_eglDisplay(display) - , m_eglConfig(config) , m_swapInterval(-1) , m_swapIntervalEnvChecked(false) , m_swapIntervalFromEnv(-1) { - init(format, share); + if (nativeHandle.isNull()) { + m_eglConfig = config ? *config : q_configFromGLFormat(display, format); + m_ownsContext = true; + init(format, share); + } else { + m_ownsContext = false; + adopt(nativeHandle, share); + } } void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share) @@ -198,6 +195,59 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont q_printEglConfig(m_eglDisplay, m_eglConfig); } + updateFormatFromGL(); +} + +void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLContext *share) +{ + if (!nativeHandle.canConvert<QEGLNativeContext>()) { + qWarning("QEGLPlatformContext: Requires a QEGLNativeContext"); + return; + } + QEGLNativeContext handle = nativeHandle.value<QEGLNativeContext>(); + EGLContext context = handle.context(); + if (!context) { + qWarning("QEGLPlatformContext: No EGLContext given"); + return; + } + + // A context belonging to a given EGLDisplay cannot be used with another one. + if (handle.display() != m_eglDisplay) { + qWarning("QEGLPlatformContext: Cannot adopt context from different display"); + return; + } + + // Figure out the EGLConfig. + EGLint value = 0; + eglQueryContext(m_eglDisplay, context, EGL_CONFIG_ID, &value); + EGLint n = 0; + EGLConfig cfg; + const EGLint attribs[] = { EGL_CONFIG_ID, value, EGL_NONE }; + if (eglChooseConfig(m_eglDisplay, attribs, &cfg, 1, &n) && n == 1) { + m_eglConfig = cfg; + m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig); + } else { + qWarning("QEGLPlatformContext: Failed to get framebuffer configuration for context"); + } + + // Fetch client API type. + value = 0; + eglQueryContext(m_eglDisplay, context, EGL_CONTEXT_CLIENT_TYPE, &value); + if (value == EGL_OPENGL_API || value == EGL_OPENGL_ES_API) { + m_api = value; + eglBindAPI(m_api); + } else { + qWarning("QEGLPlatformContext: Failed to get client API type"); + m_api = EGL_OPENGL_ES_API; + } + + m_eglContext = context; + m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0; + updateFormatFromGL(); +} + +void QEGLPlatformContext::updateFormatFromGL() +{ #ifndef QT_NO_OPENGL // Make the context current to ensure the GL version query works. This needs a surface too. const EGLint pbufferAttributes[] = { @@ -296,10 +346,10 @@ bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface) QEGLPlatformContext::~QEGLPlatformContext() { - if (m_eglContext != EGL_NO_CONTEXT) { + if (m_ownsContext && m_eglContext != EGL_NO_CONTEXT) eglDestroyContext(m_eglDisplay, m_eglContext); - m_eglContext = EGL_NO_CONTEXT; - } + + m_eglContext = EGL_NO_CONTEXT; } void QEGLPlatformContext::doneCurrent() diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h index 714633c3bc..82f062c4a4 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h @@ -44,6 +44,7 @@ #include <qpa/qplatformwindow.h> #include <qpa/qplatformopenglcontext.h> +#include <QtCore/QVariant> #include <EGL/egl.h> QT_BEGIN_NAMESPACE @@ -51,9 +52,8 @@ QT_BEGIN_NAMESPACE class QEGLPlatformContext : public QPlatformOpenGLContext { public: - QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display); QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLConfig config); + EGLConfig *config = 0, const QVariant &nativeHandle = QVariant()); ~QEGLPlatformContext(); bool makeCurrent(QPlatformSurface *surface); @@ -74,6 +74,8 @@ protected: private: void init(const QSurfaceFormat &format, QPlatformOpenGLContext *share); + void adopt(const QVariant &nativeHandle, QPlatformOpenGLContext *share); + void updateFormatFromGL(); EGLContext m_eglContext; EGLContext m_shareContext; @@ -84,6 +86,7 @@ private: int m_swapInterval; bool m_swapIntervalEnvChecked; int m_swapIntervalFromEnv; + bool m_ownsContext; }; QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp index 3de0642c93..560ff79ef8 100644 --- a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp @@ -158,9 +158,14 @@ QPlatformOpenGLContext *QEGLPlatformIntegration::createPlatformOpenGLContext(QOp // If there is a "root" window into which raster and QOpenGLWidget content is // composited, all other contexts must share with its context. QOpenGLContext *compositingContext = screen ? screen->compositingContext() : 0; - return createContext(context->format(), - compositingContext ? compositingContext->handle() : context->shareHandle(), - display()); + QPlatformOpenGLContext *share = compositingContext ? compositingContext->handle() : context->shareHandle(); + QVariant nativeHandle = context->nativeHandle(); + QPlatformOpenGLContext *platformContext = createContext(context->format(), + share, + display(), + &nativeHandle); + context->setNativeHandle(nativeHandle); + return platformContext; } QPlatformOffscreenSurface *QEGLPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h index 0de8cc9a33..9d4207e005 100644 --- a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h @@ -44,6 +44,7 @@ #include <qpa/qplatformintegration.h> #include <qpa/qplatformnativeinterface.h> +#include <QtCore/QVariant> #include <EGL/egl.h> QT_BEGIN_NAMESPACE @@ -89,7 +90,8 @@ protected: virtual QEGLPlatformWindow *createWindow(QWindow *window) const = 0; virtual QEGLPlatformContext *createContext(const QSurfaceFormat &format, QPlatformOpenGLContext *shareContext, - EGLDisplay display) const = 0; + EGLDisplay display, + QVariant *nativeHandle) const = 0; virtual QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *surface) const = 0; diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp index 4d443b91e3..71c3c1e59b 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp @@ -42,7 +42,6 @@ #include "qeglfscontext.h" #include "qeglfswindow.h" #include "qeglfshooks.h" -#include "qeglfsintegration.h" #include <QtPlatformSupport/private/qeglconvenience_p.h> #include <QtPlatformSupport/private/qeglpbuffer_p.h> @@ -52,9 +51,9 @@ QT_BEGIN_NAMESPACE -QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display) - : QEGLPlatformContext(format, share, display, - QEglFSIntegration::chooseConfig(display, format)) +QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, + EGLConfig *config, const QVariant &nativeHandle) + : QEGLPlatformContext(format, share, display, config, nativeHandle) { } diff --git a/src/plugins/platforms/eglfs/qeglfscontext.h b/src/plugins/platforms/eglfs/qeglfscontext.h index 5d406f09f1..d378b7818b 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.h +++ b/src/plugins/platforms/eglfs/qeglfscontext.h @@ -43,13 +43,15 @@ #define QEGLFSCONTEXT_H #include <QtPlatformSupport/private/qeglplatformcontext_p.h> +#include <QtCore/QVariant> QT_BEGIN_NAMESPACE class QEglFSContext : public QEGLPlatformContext { public: - QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display); + QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, + EGLConfig *config, const QVariant &nativeHandle); EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) Q_DECL_OVERRIDE; void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE; }; diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 2941806f17..d770ea763a 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -50,6 +50,7 @@ #include <QtPlatformSupport/private/qeglconvenience_p.h> #include <QtPlatformSupport/private/qeglplatformcontext_p.h> #include <QtPlatformSupport/private/qeglpbuffer_p.h> +#include <QtPlatformHeaders/QEGLNativeContext> #include <qpa/qplatformwindow.h> #include <QtGui/QSurfaceFormat> @@ -115,9 +116,20 @@ QEGLPlatformWindow *QEglFSIntegration::createWindow(QWindow *window) const QEGLPlatformContext *QEglFSIntegration::createContext(const QSurfaceFormat &format, QPlatformOpenGLContext *shareContext, - EGLDisplay display) const + EGLDisplay display, + QVariant *nativeHandle) const { - return new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display); + QEglFSContext *ctx; + if (!nativeHandle || nativeHandle->isNull()) { + EGLConfig config = QEglFSIntegration::chooseConfig(display, format); + ctx = new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display, + &config, QVariant()); + } else { + ctx = new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display, + 0, *nativeHandle); + } + *nativeHandle = QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(ctx->eglContext(), display)); + return ctx; } QPlatformOffscreenSurface *QEglFSIntegration::createOffscreenSurface(EGLDisplay display, diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h index 99dda1ea96..fea05cd400 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsintegration.h @@ -66,7 +66,8 @@ protected: QEGLPlatformWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE; QEGLPlatformContext *createContext(const QSurfaceFormat &format, QPlatformOpenGLContext *shareContext, - EGLDisplay display) const Q_DECL_OVERRIDE; + EGLDisplay display, + QVariant *nativeHandle) const Q_DECL_OVERRIDE; QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *surface) const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 2d4c523a4b..0315d0762f 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -83,6 +83,7 @@ #include "qxcbeglsurface.h" #include <QtPlatformSupport/private/qeglplatformcontext_p.h> #include <QtPlatformSupport/private/qeglpbuffer_p.h> +#include <QtPlatformHeaders/QEGLNativeContext> #endif #include <QtGui/QOpenGLContext> @@ -186,8 +187,8 @@ class QEGLXcbPlatformContext : public QEGLPlatformContext { public: QEGLXcbPlatformContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share, - EGLDisplay display, QXcbConnection *c) - : QEGLPlatformContext(glFormat, share, display) + EGLDisplay display, QXcbConnection *c, const QVariant &nativeHandle) + : QEGLPlatformContext(glFormat, share, display, 0, nativeHandle) , m_connection(c) { Q_XCB_NOOP(m_connection); @@ -223,6 +224,10 @@ public: return static_cast<QEGLPbuffer *>(surface)->pbuffer(); } + QVariant nativeHandle() const { + return QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(eglContext(), eglDisplay())); + } + private: QXcbConnection *m_connection; }; @@ -238,8 +243,13 @@ QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLCont context->setNativeHandle(platformContext->nativeHandle()); return platformContext; #elif defined(XCB_USE_EGL) - return new QEGLXcbPlatformContext(context->format(), context->shareHandle(), - screen->connection()->egl_display(), screen->connection()); + QEGLXcbPlatformContext *platformContext = new QEGLXcbPlatformContext(context->format(), + context->shareHandle(), + screen->connection()->egl_display(), + screen->connection(), + context->nativeHandle()); + context->setNativeHandle(platformContext->nativeHandle()); + return platformContext; #else Q_UNUSED(screen); qWarning("QXcbIntegration: Cannot create platform OpenGL context, neither GLX nor EGL are enabled"); |