diff options
65 files changed, 637 insertions, 977 deletions
diff --git a/examples/opengl/contextinfo/widget.cpp b/examples/opengl/contextinfo/widget.cpp index 0762c91662..ee3161eae7 100644 --- a/examples/opengl/contextinfo/widget.cpp +++ b/examples/opengl/contextinfo/widget.cpp @@ -381,8 +381,11 @@ void Widget::renderWindowReady() const char *gltype[] = { "Desktop", "GLES 2", "GLES 1" }; m_output->append(tr("Qt OpenGL configuration: %1") .arg(QString::fromLatin1(gltype[QOpenGLContext::openGLModuleType()]))); +#if defined(Q_OS_WIN) + using namespace QPlatformInterface; m_output->append(tr("Qt OpenGL library handle: %1") - .arg(QString::number(qintptr(QOpenGLContext::openGLModuleHandle()), 16))); + .arg(QString::number(qintptr(QWGLContext::openGLModuleHandle()), 16))); +#endif QList<QByteArray> extensionList = context->extensions().values(); std::sort(extensionList.begin(), extensionList.end()); diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 08e631568d..ff36c0f8e5 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1292,6 +1292,32 @@ template <bool B, typename T = void> struct QEnableIf; template <typename T> struct QEnableIf<true, T> { typedef T Type; }; } +#define QT_VA_ARGS_CHOOSE(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N +#define QT_VA_ARGS_EXPAND(...) __VA_ARGS__ // Needed for MSVC +#define QT_VA_ARGS_COUNT(...) QT_VA_ARGS_EXPAND(QT_VA_ARGS_CHOOSE(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)) +#define QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) MACRO##ARGC +#define QT_OVERLOADED_MACRO_IMP(MACRO, ARGC) QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) +#define QT_OVERLOADED_MACRO(MACRO, ...) QT_VA_ARGS_EXPAND(QT_OVERLOADED_MACRO_IMP(MACRO, QT_VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__)) + +// Ensures that the interface's typeinfo is exported so that +// dynamic casts work reliably, and protects the destructor +// so that pointers to the interface can't be deleted. +#define QT_DECLARE_PLATFORM_INTERFACE(InterfaceClass) \ + protected: virtual ~InterfaceClass(); public: + +// Provides a definition for the interface destructor +#define QT_DEFINE_PLATFORM_INTERFACE2(Namespace, InterfaceClass) \ + QT_PREPEND_NAMESPACE(Namespace)::InterfaceClass::~InterfaceClass() = default + +// Provides a definition for the destructor, and an explicit +// template instantiation of the platform interface accessor. +#define QT_DEFINE_PLATFORM_INTERFACE3(Namespace, InterfaceClass, PublicClass) \ + QT_DEFINE_PLATFORM_INTERFACE2(Namespace, InterfaceClass); \ + template Q_DECL_EXPORT QT_PREPEND_NAMESPACE(Namespace)::InterfaceClass *PublicClass::platformInterface() const + +#define QT_DEFINE_PLATFORM_INTERFACE(...) QT_OVERLOADED_MACRO(QT_DEFINE_PLATFORM_INTERFACE, QPlatformInterface, __VA_ARGS__) +#define QT_DEFINE_PRIVATE_PLATFORM_INTERFACE(...) QT_OVERLOADED_MACRO(QT_DEFINE_PLATFORM_INTERFACE, QPlatformInterface::Private, __VA_ARGS__) + QT_END_NAMESPACE // We need to keep QTypeInfo, QSysInfo, QFlags, qDebug & family in qglobal.h for compatibility with Qt 4. diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index a21ce5e65a..789476a884 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -303,13 +303,6 @@ private: return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT)); \ }() -#define QT_VA_ARGS_CHOOSE(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N -#define QT_VA_ARGS_COUNT(...) QT_VA_ARGS_CHOOSE(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1) - -#define QT_OVERLOADED_MACRO(MACRO, ...) _QT_OVERLOADED_MACRO(MACRO, QT_VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__) -#define _QT_OVERLOADED_MACRO(MACRO, ARGC) _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) -#define _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) MACRO##ARGC - #define QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(condition, description, parent) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent) #define QT_APPLE_LOG_ACTIVITY_WITH_PARENT2(description, parent) QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(true, description, parent) #define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY_WITH_PARENT, __VA_ARGS__) diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 99fe0a9b05..54420afd0d 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -347,7 +347,7 @@ endif() qt_extend_target(Gui CONDITION QT_FEATURE_opengl SOURCES - kernel/qopenglcontext.cpp kernel/qopenglcontext.h kernel/qopenglcontext_p.h + kernel/qopenglcontext.cpp kernel/qopenglcontext.h kernel/qopenglcontext_p.h kernel/qopenglcontext_platform.h kernel/qplatformopenglcontext.cpp kernel/qplatformopenglcontext.h opengl/qopengl.cpp opengl/qopengl.h opengl/qopengl_p.h opengl/qopenglextensions_p.h @@ -362,6 +362,8 @@ qt_extend_target(Gui CONDITION QT_FEATURE_opengl # MODULE_CONFIG = "opengl" qt_extend_target(Gui CONDITION MACOS + SOURCES + platform/macos/qcocoaplatforminterface.mm LIBRARIES ${FWAppKit} PUBLIC_LIBRARIES @@ -395,6 +397,7 @@ qt_extend_target(Gui CONDITION WIN32 image/qpixmap_win.cpp kernel/qwindowdefs_win.h platform/windows/qwindowsguieventdispatcher.cpp platform/windows/qwindowsguieventdispatcher_p.h + platform/windows/qwindowsplatforminterface.cpp rhi/qrhid3d11.cpp rhi/qrhid3d11_p.h rhi/qrhid3d11_p_p.h text/windows/qwindowsfontdatabase.cpp text/windows/qwindowsfontdatabase_p.h @@ -851,6 +854,7 @@ qt_extend_target(Gui CONDITION UNIX platform/unix/qgenericunixeventdispatcher.cpp platform/unix/qgenericunixeventdispatcher_p.h platform/unix/qunixeventdispatcher.cpp platform/unix/qunixeventdispatcher_qpa_p.h + platform/unix/qunixplatforminterface.cpp ) qt_extend_target(Gui CONDITION QT_FEATURE_glib AND UNIX diff --git a/src/gui/configure.json b/src/gui/configure.json index 5473f8b30c..32f1cd1b22 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -1225,7 +1225,7 @@ "egl": { "label": "EGL", "condition": "(features.opengl || features.openvg) && libs.egl && (features.dlopen || !config.unix || config.integrity)", - "output": [ "privateFeature", "feature" ] + "output": [ "publicFeature", "feature" ] }, "egl_x11": { "label": "EGL on X11", diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index afaa7de684..e653adab9c 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -161,7 +161,8 @@ qtConfig(opengl) { HEADERS += \ kernel/qplatformopenglcontext.h \ kernel/qopenglcontext.h \ - kernel/qopenglcontext_p.h + kernel/qopenglcontext_p.h \ + kernel/qopenglcontext_platform.h \ SOURCES += \ kernel/qplatformopenglcontext.cpp \ diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 5c6d082f98..51bf5cf336 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -347,63 +347,15 @@ void QOpenGLContextPrivate::_q_screenDestroyed(QObject *object) } /*! - Set the native handles for this context. When create() is called and a - native handle is set, configuration settings, like format(), are ignored - since this QOpenGLContext will wrap an already created native context - instead of creating a new one from scratch. - - On some platforms the native context handle is not sufficient and other - related handles (for example, for a window or display) have to be provided - in addition. Therefore \a handle is variant containing a platform-specific - value type. These classes can be found in the QtPlatformHeaders module. - - When create() is called with native handles set, QOpenGLContext does not - take ownership of the handles, so destroying the QOpenGLContext does not - destroy the native context. - - \note Some frameworks track the current context and surfaces internally. - Making the adopted QOpenGLContext current via Qt will have no effect on such - other frameworks' internal state. Therefore a subsequent makeCurrent done - via the other framework may have no effect. It is therefore advisable to - make explicit calls to make no context and surface current to reset the - other frameworks' internal state after performing OpenGL operations via Qt. - - \note Using foreign contexts with Qt windows and Qt contexts with windows - and surfaces created by other frameworks may give unexpected results, - depending on the platform, due to potential mismatches in context and window - pixel formats. To make sure this does not happen, avoid making contexts and - surfaces from different frameworks current together. Instead, prefer - approaches based on context sharing where OpenGL resources like textures are - accessible both from Qt's and the foreign framework's contexts. - - \since 5.4 - \sa nativeHandle() -*/ -void QOpenGLContext::setNativeHandle(const QVariant &handle) -{ - Q_D(QOpenGLContext); - d->nativeHandle = handle; -} + \fn T QOpenGLContext::platformInterface<T>() -/*! - Returns the native handle for the context. + Returns a platform interface of type T for the context. - This function provides access to the QOpenGLContext's underlying native - context. The returned variant contains a platform-specific value type. These - classes can be found in the module QtPlatformHeaders. + This function provides access to platform specific functionality + of QOpenGLContext, as defined in the QPlatformInterface namespace. - On platforms where retrieving the native handle is not supported, or if - neither create() nor setNativeHandle() was called, a null variant is - returned. - - \since 5.4 - \sa setNativeHandle() + If the requested interface is not available a \nullptr is returned. */ -QVariant QOpenGLContext::nativeHandle() const -{ - Q_D(const QOpenGLContext); - return d->nativeHandle; -} /*! Attempts to create the OpenGL context with the current configuration. @@ -433,18 +385,29 @@ bool QOpenGLContext::create() if (d->platformGLContext) destroy(); - d->platformGLContext = QGuiApplicationPrivate::platformIntegration()->createPlatformOpenGLContext(this); - if (!d->platformGLContext) + auto *platformContext = QGuiApplicationPrivate::platformIntegration()->createPlatformOpenGLContext(this); + if (!platformContext) return false; - d->platformGLContext->setContext(this); - d->platformGLContext->initialize(); - if (!d->platformGLContext->isSharing()) - d->shareContext = nullptr; - d->shareGroup = d->shareContext ? d->shareContext->shareGroup() : new QOpenGLContextGroup; - d->shareGroup->d_func()->addContext(this); + + d->adopt(platformContext); + return isValid(); } +void QOpenGLContextPrivate::adopt(QPlatformOpenGLContext *context) +{ + Q_Q(QOpenGLContext); + + platformGLContext = context; + platformGLContext->setContext(q); + platformGLContext->initialize(); + + if (!platformGLContext->isSharing()) + shareContext = nullptr; + shareGroup = shareContext ? shareContext->shareGroup() : new QOpenGLContextGroup; + shareGroup->d_func()->addContext(q); +} + /*! \internal @@ -490,8 +453,6 @@ void QOpenGLContext::destroy() d->vaoHelperDestroyCallback = nullptr; } d->vaoHelper = nullptr; - - d->nativeHandle = QVariant(); } /*! @@ -915,33 +876,6 @@ QScreen *QOpenGLContext::screen() const } /*! - Returns the platform-specific handle for the OpenGL implementation that - is currently in use. (for example, a HMODULE on Windows) - - On platforms that do not use dynamic GL switching, the return value - is \nullptr. - - The library might be GL-only, meaning that windowing system interface - functions (for example EGL) may live in another, separate library. - - \note This function requires that the QGuiApplication instance is already created. - - \sa openGLModuleType() - - \since 5.3 - */ -void *QOpenGLContext::openGLModuleHandle() -{ -#ifdef QT_OPENGL_DYNAMIC - QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface(); - Q_ASSERT(ni); - return ni->nativeResourceForIntegration(QByteArrayLiteral("glhandle")); -#else - return nullptr; -#endif -} - -/*! \enum QOpenGLContext::OpenGLModuleType This enum defines the type of the underlying OpenGL implementation. @@ -1350,8 +1284,7 @@ QDebug operator<<(QDebug debug, const QOpenGLContext *ctx) if (ctx) { debug << static_cast<const void *>(ctx); if (ctx->isValid()) { - debug << ", nativeHandle=" << ctx->nativeHandle() - << ", format=" << ctx->format(); + debug << ", format=" << ctx->format(); if (const QSurface *sf = ctx->surface()) debug << ", surface=" << sf; if (const QScreen *s = ctx->screen()) diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h index a0d8a3edba..24adb1910b 100644 --- a/src/gui/kernel/qopenglcontext.h +++ b/src/gui/kernel/qopenglcontext.h @@ -88,6 +88,7 @@ private: QOpenGLContextGroup(); friend class QOpenGLContext; + friend class QOpenGLContextPrivate; friend class QOpenGLContextGroupResourceBase; friend class QOpenGLSharedResource; friend class QOpenGLMultiGroupSharedResource; @@ -107,7 +108,6 @@ public: void setFormat(const QSurfaceFormat &format); void setShareContext(QOpenGLContext *shareContext); void setScreen(QScreen *screen); - void setNativeHandle(const QVariant &handle); bool create(); bool isValid() const; @@ -116,7 +116,6 @@ public: QOpenGLContext *shareContext() const; QOpenGLContextGroup *shareGroup() const; QScreen *screen() const; - QVariant nativeHandle() const; GLuint defaultFramebufferObject() const; @@ -141,8 +140,6 @@ public: QSet<QByteArray> extensions() const; bool hasExtension(const QByteArray &extension) const; - static void *openGLModuleHandle(); - enum OpenGLModuleType { LibGL, LibGLES @@ -155,6 +152,9 @@ public: static bool supportsThreadedOpenGL(); static QOpenGLContext *globalShareContext(); + template <typename T> + T *platformInterface() const; + Q_SIGNALS: void aboutToBeDestroyed(); @@ -188,6 +188,8 @@ Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QOpenGLContextGroup *cg); QT_END_NAMESPACE +#include <QtGui/qopenglcontext_platform.h> + #endif // QT_NO_OPENGL #endif // QOPENGLCONTEXT_H diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index c5f971fa4a..b3c0658d60 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -234,6 +234,8 @@ public: delete versionFunctions; } + void adopt(QPlatformOpenGLContext *); + QSurfaceFormat requestedFormat; QPlatformOpenGLContext *platformGLContext; QOpenGLContext *shareContext; @@ -264,7 +266,6 @@ public: // Saves us from querying the driver for the current FBO in most paths. QOpenGLFramebufferObject *qgl_current_fbo; - QVariant nativeHandle; GLuint defaultFboRedirect; static QOpenGLContext *setCurrentContext(QOpenGLContext *context); diff --git a/src/gui/kernel/qopenglcontext_platform.h b/src/gui/kernel/qopenglcontext_platform.h new file mode 100644 index 0000000000..25be8623c6 --- /dev/null +++ b/src/gui/kernel/qopenglcontext_platform.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QOPENGLCONTEXT_PLATFORM_H +#define QOPENGLCONTEXT_PLATFORM_H + +#ifndef QT_NO_OPENGL + +#include <QtGui/qtguiglobal.h> +#include <QtGui/qopenglcontext.h> +#include <QtGui/qwindowdefs.h> + +#if defined(Q_OS_MACOS) +Q_FORWARD_DECLARE_OBJC_CLASS(NSOpenGLContext); +#endif + +#if defined(Q_OS_LINUX) +struct __GLXcontextRec; typedef struct __GLXcontextRec *GLXContext; +#endif +#if QT_CONFIG(egl) +typedef void *EGLContext; +typedef void *EGLDisplay; +#endif + +QT_BEGIN_NAMESPACE + +namespace QPlatformInterface { + +#if defined(Q_OS_MACOS) +struct Q_GUI_EXPORT QCocoaGLContext +{ + QT_DECLARE_PLATFORM_INTERFACE(QCocoaGLContext) + static QOpenGLContext *fromNative(QT_IGNORE_DEPRECATIONS(NSOpenGLContext) *, QOpenGLContext *shareContext = nullptr); + virtual QT_IGNORE_DEPRECATIONS(NSOpenGLContext) *nativeContext() const = 0; +}; +#endif + +#if defined(Q_OS_WIN) +struct Q_GUI_EXPORT QWGLContext +{ + QT_DECLARE_PLATFORM_INTERFACE(QWGLContext) + static HMODULE openGLModuleHandle(); + static QOpenGLContext *fromNative(HGLRC context, HWND window, QOpenGLContext *shareContext = nullptr); + virtual HGLRC nativeContext() const = 0; +}; +#endif + +#if defined(Q_OS_LINUX) +struct Q_GUI_EXPORT QGLXContext +{ + QT_DECLARE_PLATFORM_INTERFACE(QGLXContext) + static QOpenGLContext *fromNative(GLXContext configBasedContext, QOpenGLContext *shareContext = nullptr); + static QOpenGLContext *fromNative(GLXContext visualBasedContext, void *visualInfo, QOpenGLContext *shareContext = nullptr); + virtual GLXContext nativeContext() const = 0; +}; +#endif + +#if QT_CONFIG(egl) +struct Q_GUI_EXPORT QEGLContext +{ + QT_DECLARE_PLATFORM_INTERFACE(QEGLContext) + static QOpenGLContext *fromNative(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext = nullptr); + virtual EGLContext nativeContext() const = 0; +}; +#endif + +} // QPlatformInterface + +QT_END_NAMESPACE + +#endif // QT_NO_OPENGL + +#endif // QOPENGLCONTEXT_PLATFORM_H diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h index 01406958e2..23e868180f 100644 --- a/src/gui/kernel/qplatformintegration.h +++ b/src/gui/kernel/qplatformintegration.h @@ -81,6 +81,30 @@ class QOffscreenSurface; class QPlatformVulkanInstance; class QVulkanInstance; +namespace QPlatformInterface::Private { + +template <typename R, typename I, auto func, typename... Args> +struct QInterfaceProxyImp +{ + template <typename T> + static R apply(T *obj, Args... args) + { + if (auto *iface = dynamic_cast<I*>(obj)) + return (iface->*func)(args...); + else + return R(); + } +}; + +template <auto func> +struct QInterfaceProxy; +template <typename R, typename I, typename... Args, R(I::*func)(Args...)> +struct QInterfaceProxy<func> : public QInterfaceProxyImp<R, I, func, Args...> {}; +template <typename R, typename I, typename... Args, R(I::*func)(Args...) const> +struct QInterfaceProxy<func> : public QInterfaceProxyImp<R, I, func, Args...> {}; + +} // QPlatformInterface::Private + class Q_GUI_EXPORT QPlatformIntegration { public: @@ -200,6 +224,13 @@ public: virtual QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const; #endif + template <auto func, typename... Args> + auto call(Args... args) + { + using namespace QPlatformInterface::Private; + return QInterfaceProxy<func>::apply(this, args...); + } + protected: QPlatformIntegration() = default; }; diff --git a/src/gui/kernel/qplatformopenglcontext.h b/src/gui/kernel/qplatformopenglcontext.h index f307cc14f9..8c38d88b56 100644 --- a/src/gui/kernel/qplatformopenglcontext.h +++ b/src/gui/kernel/qplatformopenglcontext.h @@ -57,6 +57,7 @@ #include <QtGui/qsurfaceformat.h> #include <QtGui/qwindow.h> #include <QtGui/qopengl.h> +#include <QtGui/qopenglcontext.h> QT_BEGIN_NAMESPACE @@ -92,6 +93,7 @@ public: private: friend class QOpenGLContext; + friend class QOpenGLContextPrivate; QScopedPointer<QPlatformOpenGLContextPrivate> d_ptr; @@ -100,6 +102,49 @@ private: Q_DISABLE_COPY(QPlatformOpenGLContext) }; +template <typename T> +T *QOpenGLContext::platformInterface() const +{ + return dynamic_cast<T*>(handle()); +} + +namespace QPlatformInterface::Private { + +#if defined(Q_OS_MACOS) +struct Q_GUI_EXPORT QCocoaGLIntegration +{ + QT_DECLARE_PLATFORM_INTERFACE(QCocoaGLIntegration) + virtual QOpenGLContext *createOpenGLContext(NSOpenGLContext *, QOpenGLContext *shareContext) const = 0; +}; +#endif + +#if defined(Q_OS_WIN) +struct Q_GUI_EXPORT QWindowsGLIntegration +{ + QT_DECLARE_PLATFORM_INTERFACE(QWindowsGLIntegration) + virtual HMODULE openGLModuleHandle() const = 0; + virtual QOpenGLContext *createOpenGLContext(HGLRC context, HWND window, QOpenGLContext *shareContext) const = 0; +}; +#endif + +#if defined(Q_OS_LINUX) +struct Q_GUI_EXPORT QGLXIntegration +{ + QT_DECLARE_PLATFORM_INTERFACE(QGLXIntegration) + virtual QOpenGLContext *createOpenGLContext(GLXContext context, void *visualInfo, QOpenGLContext *shareContext) const = 0; +}; +#endif + +#if QT_CONFIG(egl) +struct Q_GUI_EXPORT QEGLIntegration +{ + QT_DECLARE_PLATFORM_INTERFACE(QEGLIntegration) + virtual QOpenGLContext *createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const = 0; +}; +#endif + +} // QPlatformInterface::Private + QT_END_NAMESPACE #endif // QT_NO_OPENGL diff --git a/src/gui/kernel/qwindowdefs_win.h b/src/gui/kernel/qwindowdefs_win.h index b546fe305e..40074d6cce 100644 --- a/src/gui/kernel/qwindowdefs_win.h +++ b/src/gui/kernel/qwindowdefs_win.h @@ -72,6 +72,9 @@ QT_END_NAMESPACE #ifndef HINSTANCE Q_DECLARE_HANDLE(HINSTANCE); #endif +#ifndef HMODULE +typedef HINSTANCE HMODULE; +#endif #ifndef HDC Q_DECLARE_HANDLE(HDC); #endif @@ -105,6 +108,9 @@ Q_DECLARE_HANDLE(HRGN); #ifndef HMONITOR Q_DECLARE_HANDLE(HMONITOR); #endif +#ifndef HGLRC +Q_DECLARE_HANDLE(HGLRC); +#endif #ifndef _HRESULT_DEFINED typedef long HRESULT; #endif diff --git a/src/gui/platform/macos/macos.pri b/src/gui/platform/macos/macos.pri new file mode 100644 index 0000000000..f0107c6944 --- /dev/null +++ b/src/gui/platform/macos/macos.pri @@ -0,0 +1,4 @@ +SOURCES += \ + $$PWD/qcocoaplatforminterface.mm + +LIBS_PRIVATE += -framework AppKit diff --git a/src/platformheaders/nativecontexts/qwglnativecontext.h b/src/gui/platform/macos/qcocoaplatforminterface.mm index 24244b285f..a1410a63b2 100644 --- a/src/platformheaders/nativecontexts/qwglnativecontext.h +++ b/src/gui/platform/macos/qcocoaplatforminterface.mm @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage @@ -37,43 +37,24 @@ ** ****************************************************************************/ -#ifndef QWGLNATIVECONTEXT_H -#define QWGLNATIVECONTEXT_H +#include <QtGui/private/qopenglcontext_p.h> +#include <QtGui/private/qguiapplication_p.h> +#include <qpa/qplatformopenglcontext.h> +#include <qpa/qplatformintegration.h> -#include <QtCore/QMetaType> -#include <wingdi.h> -#include <GL/gl.h> +#include <AppKit/AppKit.h> QT_BEGIN_NAMESPACE -#if defined(Q_CLANG_QDOC) -typedef int HGLRC; -typedef int HWND; -#endif +using namespace QPlatformInterface::Private; -class QWGLNativeContext -{ -public: - QWGLNativeContext() - : m_context(0), - m_window(0) - { } - - QWGLNativeContext(HGLRC ctx, HWND wnd) - : m_context(ctx), - m_window(wnd) - { } - - HGLRC context() const { return m_context; } - HWND window() const { return m_window; } +QT_DEFINE_PLATFORM_INTERFACE(QCocoaGLContext, QOpenGLContext); +QT_DEFINE_PRIVATE_PLATFORM_INTERFACE(QCocoaGLIntegration); -private: - HGLRC m_context; - HWND m_window; -}; +QOpenGLContext *QPlatformInterface::QCocoaGLContext::fromNative(NSOpenGLContext *nativeContext, QOpenGLContext *shareContext) +{ + return QGuiApplicationPrivate::platformIntegration()->call< + &QCocoaGLIntegration::createOpenGLContext>(nativeContext, shareContext); +} QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QWGLNativeContext) - -#endif // QWGLNATIVECONTEXT_H diff --git a/src/gui/platform/platform.pri b/src/gui/platform/platform.pri index 14a10d10b1..71cffb403e 100644 --- a/src/gui/platform/platform.pri +++ b/src/gui/platform/platform.pri @@ -2,3 +2,4 @@ wasm:include(wasm/wasm.pri) darwin:include(darwin/darwin.pri) win32:include(windows/windows.pri) unix:include(unix/unix.pri) +macos:include(macos/macos.pri) diff --git a/src/platformheaders/nativecontexts/qglxnativecontext.h b/src/gui/platform/unix/qunixplatforminterface.cpp index 989d68eb9e..a090ef6601 100644 --- a/src/platformheaders/nativecontexts/qglxnativecontext.h +++ b/src/gui/platform/unix/qunixplatforminterface.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage @@ -37,52 +37,44 @@ ** ****************************************************************************/ -#ifndef QGLXNATIVECONTEXT_H -#define QGLXNATIVECONTEXT_H +#include <QtGui/private/qtguiglobal_p.h> -#include <QtCore/QMetaType> -#include <X11/Xlib.h> -#include <GL/glx.h> +#include <QtGui/private/qopenglcontext_p.h> +#include <QtGui/private/qguiapplication_p.h> + +#include <qpa/qplatformopenglcontext.h> +#include <qpa/qplatformintegration.h> QT_BEGIN_NAMESPACE -#if defined(Q_CLANG_QDOC) -typedef int GLXContext; -typedef void Display; -typedef int Window; -typedef int VisualID; -#endif +using namespace QPlatformInterface::Private; + +#if defined(Q_OS_LINUX) +QT_DEFINE_PLATFORM_INTERFACE(QGLXContext, QOpenGLContext); +QT_DEFINE_PRIVATE_PLATFORM_INTERFACE(QGLXIntegration); -struct QGLXNativeContext +QOpenGLContext *QPlatformInterface::QGLXContext::fromNative(GLXContext configBasedContext, QOpenGLContext *shareContext) { - QGLXNativeContext() - : m_context(nullptr), - m_display(nullptr), - m_window(0), - m_visualId(0) - { } + return QGuiApplicationPrivate::platformIntegration()->call< + &QGLXIntegration::createOpenGLContext>(configBasedContext, nullptr, shareContext); +} - QGLXNativeContext(GLXContext ctx, Display *dpy = nullptr, Window wnd = 0, VisualID vid = 0) - : m_context(ctx), - m_display(dpy), - m_window(wnd), - m_visualId(vid) - { } +QOpenGLContext *QPlatformInterface::QGLXContext::fromNative(GLXContext visualBasedContext, void *visualInfo, QOpenGLContext *shareContext) +{ + return QGuiApplicationPrivate::platformIntegration()->call< + &QGLXIntegration::createOpenGLContext>(visualBasedContext, visualInfo, shareContext); +} +#endif - GLXContext context() const { return m_context; } - Display *display() const { return m_display; } - Window window() const { return m_window; } - VisualID visualId() const { return m_visualId; } +#if QT_CONFIG(egl) +QT_DEFINE_PLATFORM_INTERFACE(QEGLContext, QOpenGLContext); +QT_DEFINE_PRIVATE_PLATFORM_INTERFACE(QEGLIntegration); -private: - GLXContext m_context; - Display *m_display; - Window m_window; - VisualID m_visualId; -}; +QOpenGLContext *QPlatformInterface::QEGLContext::fromNative(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) +{ + return QGuiApplicationPrivate::platformIntegration()->call< + &QEGLIntegration::createOpenGLContext>(context, display, shareContext); +} +#endif QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QGLXNativeContext) - -#endif // QGLXNATIVECONTEXT_H diff --git a/src/gui/platform/unix/unix.pri b/src/gui/platform/unix/unix.pri index 82eb63b11b..b12f3147a3 100644 --- a/src/gui/platform/unix/unix.pri +++ b/src/gui/platform/unix/unix.pri @@ -1,6 +1,7 @@ SOURCES += \ platform/unix/qunixeventdispatcher.cpp \ - platform/unix/qgenericunixeventdispatcher.cpp + platform/unix/qgenericunixeventdispatcher.cpp \ + platform/unix/qunixplatforminterface.cpp HEADERS += \ platform/unix/qunixeventdispatcher_qpa_p.h \ diff --git a/src/platformheaders/nativecontexts/qeglnativecontext.h b/src/gui/platform/windows/qwindowsplatforminterface.cpp index 5af2b304fe..ceb65cda5b 100644 --- a/src/platformheaders/nativecontexts/qeglnativecontext.h +++ b/src/gui/platform/windows/qwindowsplatforminterface.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage @@ -37,42 +37,28 @@ ** ****************************************************************************/ -#ifndef QEGLNATIVECONTEXT_H -#define QEGLNATIVECONTEXT_H - -#include <QtCore/QMetaType> - -// Leave including egl.h with the appropriate defines to the client. +#include <QtGui/qopenglcontext.h> +#include <QtGui/private/qguiapplication_p.h> +#include <qpa/qplatformopenglcontext.h> +#include <qpa/qplatformintegration.h> QT_BEGIN_NAMESPACE -#if defined(Q_CLANG_QDOC) -typedef int EGLContext; -typedef int EGLDisplay; -#endif - -struct QEGLNativeContext -{ - QEGLNativeContext() - : m_context(nullptr), - m_display(nullptr) - { } +using namespace QPlatformInterface::Private; - QEGLNativeContext(EGLContext ctx, EGLDisplay dpy) - : m_context(ctx), - m_display(dpy) - { } +QT_DEFINE_PLATFORM_INTERFACE(QWGLContext, QOpenGLContext); +QT_DEFINE_PRIVATE_PLATFORM_INTERFACE(QWindowsGLIntegration); - EGLContext context() const { return m_context; } - EGLDisplay display() const { return m_display; } +HMODULE QPlatformInterface::QWGLContext::openGLModuleHandle() +{ + return QGuiApplicationPrivate::platformIntegration()->call< + &QWindowsGLIntegration::openGLModuleHandle>(); +} -private: - EGLContext m_context; - EGLDisplay m_display; -}; +QOpenGLContext *QPlatformInterface::QWGLContext::fromNative(HGLRC context, HWND window, QOpenGLContext *shareContext) +{ + return QGuiApplicationPrivate::platformIntegration()->call< + &QWindowsGLIntegration::createOpenGLContext>(context, window, shareContext); +} QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QEGLNativeContext) - -#endif // QEGLNATIVECONTEXT_H diff --git a/src/gui/platform/windows/windows.pri b/src/gui/platform/windows/windows.pri index 809576ab31..b1e80f6538 100644 --- a/src/gui/platform/windows/windows.pri +++ b/src/gui/platform/windows/windows.pri @@ -1,2 +1,4 @@ HEADERS += platform/windows/qwindowsguieventdispatcher_p.h -SOURCES += platform/windows/qwindowsguieventdispatcher.cpp +SOURCES += \ + platform/windows/qwindowsguieventdispatcher.cpp \ + platform/windows/qwindowsplatforminterface.cpp diff --git a/src/platformheaders/nativecontexts/nativecontexts.pri b/src/platformheaders/nativecontexts/nativecontexts.pri deleted file mode 100644 index cfb190e4fa..0000000000 --- a/src/platformheaders/nativecontexts/nativecontexts.pri +++ /dev/null @@ -1,4 +0,0 @@ -HEADERS += $$PWD/qglxnativecontext.h \ - $$PWD/qeglnativecontext.h \ - $$PWD/qcocoanativecontext.h \ - $$PWD/qwglnativecontext.h diff --git a/src/platformheaders/nativecontexts/qcocoanativecontext.h b/src/platformheaders/nativecontexts/qcocoanativecontext.h deleted file mode 100644 index 8227485b15..0000000000 --- a/src/platformheaders/nativecontexts/qcocoanativecontext.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** - ** - ** Copyright (C) 2016 The Qt Company Ltd. - ** Contact: https://www.qt.io/licensing/ - ** - ** 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 The Qt Company. For licensing terms - ** and conditions see https://www.qt.io/terms-conditions. For further - ** information use the contact form at https://www.qt.io/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 3 as published by the Free Software - ** Foundation and appearing in the file LICENSE.LGPL3 included in the - ** packaging of this file. Please review the following information to - ** ensure the GNU Lesser General Public License version 3 requirements - ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. - ** - ** GNU General Public License Usage - ** Alternatively, this file may be used under the terms of the GNU - ** General Public License version 2.0 or (at your option) the GNU General - ** Public license version 3 or any later version approved by the KDE Free - ** Qt Foundation. The licenses are as published by the Free Software - ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 - ** included in the packaging of this file. Please review the following - ** information to ensure the GNU General Public License requirements will - ** be met: https://www.gnu.org/licenses/gpl-2.0.html and - ** https://www.gnu.org/licenses/gpl-3.0.html. - ** - ** $QT_END_LICENSE$ - ** - ****************************************************************************/ - -#ifndef QCOCOANATIVECONTEXT_H -#define QCOCOANATIVECONTEXT_H - -#include <QtCore/QMetaType> -#include <AppKit/NSOpenGL.h> - -QT_BEGIN_NAMESPACE - -#if defined(Q_CLANG_QDOC) -typedef void NSOpenGLContext; -#endif - -struct QCocoaNativeContext -{ - QCocoaNativeContext() - : m_context(0) - { } - - QCocoaNativeContext(NSOpenGLContext *ctx) - : m_context(ctx) - { } - - NSOpenGLContext *context() const { return m_context; } - -private: - NSOpenGLContext *m_context; -}; - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QCocoaNativeContext) - -#endif // QCOCOANATIVECONTEXT_H diff --git a/src/platformheaders/nativecontexts/qcocoanativecontext.qdoc b/src/platformheaders/nativecontexts/qcocoanativecontext.qdoc deleted file mode 100644 index 7cb4138207..0000000000 --- a/src/platformheaders/nativecontexts/qcocoanativecontext.qdoc +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QCocoaNativeContext - \inmodule QtPlatformHeaders - \since 5.4 - - \brief A class encapsulating a Cocoa NSOpenGLContext. - - \note 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 NSOpenGLContext *QCocoaNativeContext::context() const - - \return the context. - */ - -/*! - \fn QCocoaNativeContext::QCocoaNativeContext() - - Construct a new instance with no handles. - */ - -/*! - \fn QCocoaNativeContext::QCocoaNativeContext(NSOpenGLContext *ctx) - - Constructs a new instance with the provided \a ctx handle. - */ diff --git a/src/platformheaders/nativecontexts/qeglnativecontext.qdoc b/src/platformheaders/nativecontexts/qeglnativecontext.qdoc deleted file mode 100644 index 3779ea10c8..0000000000 --- a/src/platformheaders/nativecontexts/qeglnativecontext.qdoc +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QEGLNativeContext - \inmodule QtPlatformHeaders - \since 5.4 - - \brief A class encapsulating an EGL context and display handle. - - \note 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. - - \note Due to being public while relying on otherwise hidden EGL types, this header - itself does not include \c{EGL/egl.h}. It is the application's responsibility to - include egl.h with any appropriate defines (for example, \c{MESA_EGL_NO_X11_HEADERS} - or other vendor-specific defines controlling the typedefs for EGL's native resources) - before this header. - - \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/platformheaders/nativecontexts/qglxnativecontext.qdoc b/src/platformheaders/nativecontexts/qglxnativecontext.qdoc deleted file mode 100644 index 56182534a5..0000000000 --- a/src/platformheaders/nativecontexts/qglxnativecontext.qdoc +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGLXNativeContext - \inmodule QtPlatformHeaders - \since 5.4 - - \brief A class encapsulating a GLXContext and related native handles. - - \note Only context() is guaranteed to be valid. The other handles may be all \c 0. They are - useful however when QOpenGLContext::setNativeHandle() is used to adopt a legacy context - created by glXCreateContext. To adopt such a context, either the Window or VisualID - that had been used to create the context needs to be known, otherwise the adoption will - fail. For modern contexts created with an FBConfig, these are not necessary, the - GLXContext itself is sufficient. The Display is optional. - - \note 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 GLXContext QGLXNativeContext::context() const - - \return the GLXContext. - */ - -/*! - \fn Display *QGLXNativeContext::display() const - - \return a pointer to the X11 display or \c NULL if not available. - */ - -/*! - \fn Window QGLXNativeContext::window() const - - \return the X11 Window or \c 0 if not available. - */ - -/*! - \fn VisualID QGLXNativeContext::visualId() const - - \return the X11 visual ID or \c 0 if not available. - */ - -/*! - \fn QGLXNativeContext::QGLXNativeContext() - - Construct a new instance with no handles. - */ - -/*! - \fn QGLXNativeContext::QGLXNativeContext(GLXContext ctx, Display *dpy, Window wnd, VisualID vid) - - Constructs a new instance with the provided \a ctx, \a dpy, \a wnd, \a vid handles. - */ diff --git a/src/platformheaders/nativecontexts/qwglnativecontext.qdoc b/src/platformheaders/nativecontexts/qwglnativecontext.qdoc deleted file mode 100644 index 20563c3906..0000000000 --- a/src/platformheaders/nativecontexts/qwglnativecontext.qdoc +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QWGLNativeContext - \inmodule QtPlatformHeaders - \since 5.4 - - \brief A class encapsulating a WGL context on Windows with desktop OpenGL (opengl32.dll). - - \note 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. - - QWGLNativeContext is a value class that can be passed to - QOpenGLContext::setNativeHandle(). When creating a QOpenGLContext with the - native handle set, no new context will get created. Instead, the provided - handles are used, without taking ownership. This allows wrapping a context - created by an external framework or rendering engine. The typical usage will - be similar to the following snippet: - - \code - #include <QtPlatformSupport/QWGLNativeContext> - ...create and retrieve the WGL context and the corresponding window... - QOpenGLContext *context = new QOpenGLContext; - QWGLNativeContext nativeContext(hglrc, hwnd); - context->setNativeHandle(QVariant::fromValue(nativeContext)); - context->create(); - ... - \endcode - - The window is needed because the its pixel format will be queried. When the - adoption is successful, QOpenGLContext::format() will return a QSurfaceFormat - describing this pixel format. - - It is recommended to restrict the usage of QOpenGLContexts created this way. - Various platform-specific behavior and issues may prevent such contexts to be - made current with windows (surfaces) created by Qt due to non-matching pixel - formats for example. A potentially safer solution is to use the wrapped - context only to set up sharing and perform Qt-based rendering offscreen, - using a separate, dedicated QOpenGLContext. The resulting textures are then - accessible in the foreign context too. - - \code - ...like above... - QOpenGLContext *qtcontext = new QOpenGLContext; - qtcontext->setShareContext(context); - qtcontext->setFormat(context->format()); - qtcontext->create(); - ...use qtcontext for rendering with Qt... - \endcode - - In addition to being used with QOpenGLContext::setNativeHandle(), this class - is used also to retrieve the native context handle, that is, a HGLRC value, - from a QOpenGLContext. Calling QOpenGLContext::nativeHandle() returns a - QVariant which, on Windows with opengl32.dll at least, will contain a - QWGLNativeContext: - - \code - QVariant nativeHandle = context->nativeHandle(); - if (!nativeHandle.isNull() && nativeHandle.canConvert<QWGLNativeContext>()) { - QWGLNativeContext nativeContext = nativeHandle.value<QWGLNativeContext>(); - HGLRC hglrc = nativeContext.context(); - ... - } - \endcode - - \sa QOpenGLContext::setNativeHandle(), QOpenGLContext::nativeHandle() - */ - -/*! - \fn HGLRC QWGLNativeContext::context() const - - \return the WGL context. - */ - -/*! - \fn HWND QWGLNativeContext::window() const - - \note The window handle is not available when the QWGLNativeContext is - queried from a regular, non-adopted QOpenGLContext using - QOpenGLContext::nativeHandle(). This is because the \e windows platform - plugin creates WGL contexts using a dummy window that is not available - afterwards. Instead, the native window handle (HWND) is queriable from a - QWindow via QPlatformNativeInterface::nativeResourceForWindow() using the \e - "handle" resource key. Note however that the window will not have its pixel - format set until it is first associated with a context via - QOpenGLContext::makeCurrent(). - - \return handle for the window for which the context was created. - */ - -/*! - \fn QWGLNativeContext::QWGLNativeContext() - - Construct a new instance with no handles. - */ - -/*! - \fn QWGLNativeContext::QWGLNativeContext(HGLRC ctx, HWND wnd) - - Constructs a new instance with the provided \a ctx context handle and \a wnd window handle. - - \note The window specified by \a wnd must have its pixel format set to a - format compatible with the context's. If no SetPixelFormat() call was made on - any device context belonging to the window, adopting the context will fail. - */ diff --git a/src/platformheaders/platformheaders.pro b/src/platformheaders/platformheaders.pro index 392acc54f0..22d1655c77 100644 --- a/src/platformheaders/platformheaders.pro +++ b/src/platformheaders/platformheaders.pro @@ -3,7 +3,6 @@ TEMPLATE = subdirs VERSION = $$MODULE_VERSION MODULE_INCNAME = QtPlatformHeaders -include(nativecontexts/nativecontexts.pri) include(xcbfunctions/xcbfunctions.pri) include(eglfsfunctions/eglfsfunctions.pri) include(windowsfunctions/windowsfunctions.pri) diff --git a/src/platformsupport/eglconvenience/CMakeLists.txt b/src/platformsupport/eglconvenience/CMakeLists.txt index 1858dc7e90..4b709161fd 100644 --- a/src/platformsupport/eglconvenience/CMakeLists.txt +++ b/src/platformsupport/eglconvenience/CMakeLists.txt @@ -48,6 +48,6 @@ qt_extend_target(EglSupport CONDITION NOT QT_FEATURE_egl_x11 ) qt_extend_target(EglSupport CONDITION QT_FEATURE_dlopen - PUBLIC_LIBRARIES + LIBRARIES ${CMAKE_DL_LIBS} ) diff --git a/src/platformsupport/eglconvenience/eglconvenience.pro b/src/platformsupport/eglconvenience/eglconvenience.pro index df21f14697..e9ee52b53b 100644 --- a/src/platformsupport/eglconvenience/eglconvenience.pro +++ b/src/platformsupport/eglconvenience/eglconvenience.pro @@ -38,6 +38,6 @@ qtConfig(egl_x11) { } CONFIG += egl -qtConfig(dlopen): QMAKE_USE += libdl +qtConfig(dlopen): QMAKE_USE_PRIVATE += libdl load(qt_module) diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index d38a850065..c82473ebbb 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -42,7 +42,6 @@ #include "qeglpbuffer_p.h" #include <qpa/qplatformwindow.h> #include <QOpenGLContext> -#include <QtPlatformHeaders/QEGLNativeContext> #include <QDebug> #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) @@ -115,25 +114,13 @@ QT_BEGIN_NAMESPACE #endif QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLConfig *config, const QVariant &nativeHandle, Flags flags) + EGLConfig *config, Flags flags) : m_eglDisplay(display) - , m_swapInterval(-1) - , m_swapIntervalEnvChecked(false) - , m_swapIntervalFromEnv(-1) , m_flags(flags) + , m_ownsContext(true) { - if (nativeHandle.isNull()) { - m_eglConfig = config ? *config : q_configFromGLFormat(display, format); - m_ownsContext = true; - init(format, share); - } else { - m_ownsContext = false; - adopt(nativeHandle, share); - } -} + m_eglConfig = config ? *config : q_configFromGLFormat(display, format); -void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share) -{ m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig, format); // m_format now has the renderableType() resolved (it cannot be Default anymore) // but does not yet contain version, profile, options. @@ -212,24 +199,11 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont // Cannot just call updateFormatFromGL() since it relies on virtuals. Defer it to initialize(). } -void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLContext *share) +void QEGLPlatformContext::adopt(EGLContext context, EGLDisplay display, QPlatformOpenGLContext *share) { - if (!nativeHandle.canConvert<QEGLNativeContext>()) { - qWarning("QEGLPlatformContext: Requires a QEGLNativeContext"); - return; - } - QEGLNativeContext handle = qvariant_cast<QEGLNativeContext>(nativeHandle); - EGLContext context = handle.context(); - if (!context) { - qWarning("QEGLPlatformContext: No EGLContext given"); - return; - } + Q_ASSERT(!m_ownsContext); - // 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; - } + m_eglDisplay = display; // Figure out the EGLConfig. EGLint value = 0; diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h index f0388cd29c..610588568e 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h @@ -56,10 +56,12 @@ #include <qpa/qplatformopenglcontext.h> #include <QtCore/QVariant> #include <QtEglSupport/private/qt_egl_p.h> +#include <QtGui/private/qopenglcontext_p.h> QT_BEGIN_NAMESPACE -class QEGLPlatformContext : public QPlatformOpenGLContext +class QEGLPlatformContext : public QPlatformOpenGLContext, + public QPlatformInterface::QEGLContext { public: enum Flag { @@ -68,8 +70,31 @@ public: Q_DECLARE_FLAGS(Flags, Flag) QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLConfig *config = nullptr, const QVariant &nativeHandle = QVariant(), - Flags flags = { }); + EGLConfig *config = nullptr, Flags flags = { }); + + template <typename T> + static QOpenGLContext *createFrom(EGLContext context, EGLDisplay contextDisplay, + EGLDisplay platformDisplay, QOpenGLContext *shareContext) + { + if (!context) + return nullptr; + + // A context belonging to a given EGLDisplay cannot be used with another one + if (contextDisplay != platformDisplay) { + qWarning("QEGLPlatformContext: Cannot adopt context from different display"); + return nullptr; + } + + QPlatformOpenGLContext *shareHandle = shareContext ? shareContext->handle() : nullptr; + + auto *resultingContext = new QOpenGLContext; + auto *contextPrivate = QOpenGLContextPrivate::get(resultingContext); + auto *platformContext = new T; + platformContext->adopt(context, contextDisplay, shareHandle); + contextPrivate->adopt(platformContext); + return resultingContext; + } + ~QEGLPlatformContext(); void initialize() override; @@ -82,19 +107,21 @@ public: bool isSharing() const override { return m_shareContext != EGL_NO_CONTEXT; } bool isValid() const override { return m_eglContext != EGL_NO_CONTEXT; } + EGLContext nativeContext() const override { return eglContext(); } + EGLContext eglContext() const; EGLDisplay eglDisplay() const; EGLConfig eglConfig() const; protected: + QEGLPlatformContext() {} // For adoption virtual EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) = 0; virtual EGLSurface createTemporaryOffscreenSurface(); virtual void destroyTemporaryOffscreenSurface(EGLSurface surface); virtual void runGLChecks(); private: - void init(const QSurfaceFormat &format, QPlatformOpenGLContext *share); - void adopt(const QVariant &nativeHandle, QPlatformOpenGLContext *share); + void adopt(EGLContext context, EGLDisplay display, QPlatformOpenGLContext *shareContext); void updateFormatFromGL(); EGLContext m_eglContext; @@ -103,11 +130,11 @@ private: EGLConfig m_eglConfig; QSurfaceFormat m_format; EGLenum m_api; - int m_swapInterval; - bool m_swapIntervalEnvChecked; - int m_swapIntervalFromEnv; + int m_swapInterval = -1; + bool m_swapIntervalEnvChecked = false; + int m_swapIntervalFromEnv = -1; Flags m_flags; - bool m_ownsContext; + bool m_ownsContext = false; QVector<EGLint> m_contextAttrs; }; diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 3d495724c6..f4c292fe73 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -71,8 +71,6 @@ #include "qandroidsystemlocale.h" #include "qandroidplatformoffscreensurface.h" -#include <QtPlatformHeaders/QEGLNativeContext> - #if QT_CONFIG(vulkan) #include "qandroidplatformvulkanwindow.h" #include "qandroidplatformvulkaninstance.h" @@ -307,11 +305,15 @@ QPlatformOpenGLContext *QAndroidPlatformIntegration::createPlatformOpenGLContext format.setRedBufferSize(8); format.setGreenBufferSize(8); format.setBlueBufferSize(8); - auto ctx = new QAndroidPlatformOpenGLContext(format, context->shareHandle(), m_eglDisplay, context->nativeHandle()); - context->setNativeHandle(QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(ctx->eglContext(), m_eglDisplay))); + auto ctx = new QAndroidPlatformOpenGLContext(format, context->shareHandle(), m_eglDisplay); return ctx; } +QOpenGLContext *QAndroidPlatformIntegration::createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const +{ + return QEGLPlatformContext::createFrom<QAndroidPlatformOpenGLContext>(context, display, m_eglDisplay, shareContext); +} + QPlatformOffscreenSurface *QAndroidPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const { if (!QtAndroid::activity()) diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index e6a36240d0..30ab42ab34 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -45,6 +45,7 @@ #include <qpa/qplatformintegration.h> #include <qpa/qplatformmenu.h> #include <qpa/qplatformnativeinterface.h> +#include <qpa/qplatformopenglcontext.h> #include <EGL/egl.h> #include <jni.h> @@ -73,6 +74,7 @@ protected: }; class QAndroidPlatformIntegration : public QPlatformIntegration + , QPlatformInterface::Private::QEGLIntegration { friend class QAndroidPlatformScreen; @@ -88,6 +90,7 @@ public: QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override; QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; + QOpenGLContext *createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const override; QAbstractEventDispatcher *createEventDispatcher() const override; QAndroidPlatformScreen *screen() { return m_primaryScreen; } QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override; diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp index 8d98882e9e..ecbd282c91 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp +++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp @@ -51,9 +51,8 @@ QT_BEGIN_NAMESPACE -QAndroidPlatformOpenGLContext::QAndroidPlatformOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - const QVariant &nativeHandle) - :QEGLPlatformContext(format, share, display, nullptr, nativeHandle) +QAndroidPlatformOpenGLContext::QAndroidPlatformOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display) + : QEGLPlatformContext(format, share, display, nullptr) { } diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.h b/src/plugins/platforms/android/qandroidplatformopenglcontext.h index 8e65b4cc36..50559e281e 100644 --- a/src/plugins/platforms/android/qandroidplatformopenglcontext.h +++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.h @@ -48,13 +48,13 @@ QT_BEGIN_NAMESPACE class QAndroidPlatformOpenGLContext : public QEGLPlatformContext { public: - QAndroidPlatformOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, const QVariant &nativeHandle); + using QEGLPlatformContext::QEGLPlatformContext; + QAndroidPlatformOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display); void swapBuffers(QPlatformSurface *surface) override; bool makeCurrent(QPlatformSurface *surface) override; private: EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override; - }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h index f1851a2336..9dbd1a11bf 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.h +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h @@ -43,7 +43,8 @@ #include <QtCore/QPointer> #include <QtCore/private/qcore_mac_p.h> #include <qpa/qplatformopenglcontext.h> -#include <QtGui/QOpenGLContext> +#include <QtGui/qopenglcontext.h> +#include <QtGui/private/qopenglcontext_p.h> #include <QtGui/QWindow> Q_FORWARD_DECLARE_OBJC_CLASS(NSOpenGLContext); @@ -53,10 +54,11 @@ QT_BEGIN_NAMESPACE class QCocoaWindow; -class QCocoaGLContext : public QPlatformOpenGLContext +class QCocoaGLContext : public QPlatformOpenGLContext, public QPlatformInterface::QCocoaGLContext { public: QCocoaGLContext(QOpenGLContext *context); + QCocoaGLContext(NSOpenGLContext *context); ~QCocoaGLContext(); void initialize() override; @@ -71,7 +73,7 @@ public: bool isSharing() const override; bool isValid() const override; - NSOpenGLContext *nativeContext() const; + NSOpenGLContext *nativeContext() const override; QFunctionPointer getProcAddress(const char *procName) override; diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index c049ca60f2..c2fcb6cdbc 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -45,7 +45,6 @@ #include "qcocoascreen.h" #include <qdebug.h> -#include <QtPlatformHeaders/qcocoanativecontext.h> #include <dlfcn.h> static inline QByteArray getGlString(GLenum param) @@ -65,30 +64,23 @@ QCocoaGLContext::QCocoaGLContext(QOpenGLContext *context) { } -void QCocoaGLContext::initialize() +QCocoaGLContext::QCocoaGLContext(NSOpenGLContext *nativeContext) + : QPlatformOpenGLContext() { - QVariant nativeHandle = context()->nativeHandle(); - if (!nativeHandle.isNull()) { - if (!nativeHandle.canConvert<QCocoaNativeContext>()) { - qCWarning(lcQpaOpenGLContext, "QOpenGLContext native handle must be a QCocoaNativeContext"); - return; - } - m_context = nativeHandle.value<QCocoaNativeContext>().context(); - if (!m_context) { - qCWarning(lcQpaOpenGLContext, "QCocoaNativeContext's NSOpenGLContext cannot be null"); - return; - } - - [m_context retain]; - - // Note: We have no way of knowing whether the NSOpenGLContext was created with the - // share context as reported by the QOpenGLContext, but we just have to trust that - // it was. It's okey, as the only thing we're using it for is to report isShared(). - if (QPlatformOpenGLContext *shareContext = context()->shareHandle()) - m_shareContext = static_cast<QCocoaGLContext *>(shareContext)->nativeContext(); + m_context = [nativeContext retain]; +} - updateSurfaceFormat(); - return; +void QCocoaGLContext::initialize() +{ + if (m_context) { + // Note: We have no way of knowing whether the NSOpenGLContext was created with the + // share context as reported by the QOpenGLContext, but we just have to trust that + // it was. It's okey, as the only thing we're using it for is to report isShared(). + if (QPlatformOpenGLContext *shareContext = context()->shareHandle()) + m_shareContext = static_cast<QCocoaGLContext *>(shareContext)->nativeContext(); + + updateSurfaceFormat(); + return; } // ----------- Default case, we own the NSOpenGLContext ----------- @@ -139,9 +131,6 @@ void QCocoaGLContext::initialize() return; } - // The native handle should reflect the underlying context, even if we created it - context()->setNativeHandle(QVariant::fromValue<QCocoaNativeContext>(m_context)); - // --------------------- Set NSOpenGLContext properties --------------------- const GLint interval = m_format.swapInterval() >= 0 ? m_format.swapInterval() : 1; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index d2fffc8e73..f82e0050ae 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -56,12 +56,14 @@ #include <QtCore/QScopedPointer> #include <qpa/qplatformintegration.h> #include <QtGui/private/qcoretextfontdatabase_p.h> +#include <QtGui/private/qopenglcontext_p.h> Q_FORWARD_DECLARE_OBJC_CLASS(NSToolbar); QT_BEGIN_NAMESPACE -class QCocoaIntegration : public QObject, public QPlatformIntegration +class QCocoaIntegration : public QObject, public QPlatformIntegration, + public QPlatformInterface::Private::QCocoaGLIntegration { Q_OBJECT public: @@ -82,6 +84,7 @@ public: QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override; #ifndef QT_NO_OPENGL QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; + QOpenGLContext *createOpenGLContext(NSOpenGLContext *, QOpenGLContext *shareContext) const override; #endif QPlatformBackingStore *createPlatformBackingStore(QWindow *widget) const override; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 49e8f8eada..b3d3bb34bf 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -64,9 +64,8 @@ #include <qpa/qplatformoffscreensurface.h> #include <QtCore/qcoreapplication.h> -#include <QtPlatformHeaders/qcocoanativecontext.h> - #include <QtGui/private/qcoregraphics_p.h> +#include <QtGui/private/qopenglcontext_p.h> #include <QtGui/private/qfontengine_coretext_p.h> @@ -308,6 +307,19 @@ QPlatformOpenGLContext *QCocoaIntegration::createPlatformOpenGLContext(QOpenGLCo { return new QCocoaGLContext(context); } + +QOpenGLContext *QCocoaIntegration::createOpenGLContext(NSOpenGLContext *nativeContext, QOpenGLContext *shareContext) const +{ + if (!nativeContext) + return nullptr; + + auto *context = new QOpenGLContext; + context->setShareContext(shareContext); + auto *contextPrivate = QOpenGLContextPrivate::get(context); + contextPrivate->adopt(new QCocoaGLContext(nativeContext)); + return context; +} + #endif QPlatformBackingStore *QCocoaIntegration::createPlatformBackingStore(QWindow *window) const diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index 45330cf1b8..7d4c5884b3 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -59,18 +59,10 @@ class QCocoaNativeInterface : public QPlatformNativeInterface public: QCocoaNativeInterface(); -#ifndef QT_NO_OPENGL - void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) override; -#endif void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) override; NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) override; -#ifndef QT_NO_OPENGL - static void *cglContextForContext(QOpenGLContext *context); - static void *nsOpenGLContextForContext(QOpenGLContext* context); -#endif - QFunctionPointer platformFunction(const QByteArray &function) const override; public Q_SLOTS: diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index ba4ad719d2..22bab0886d 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -76,20 +76,6 @@ QCocoaNativeInterface::QCocoaNativeInterface() { } -#ifndef QT_NO_OPENGL -void *QCocoaNativeInterface::nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) -{ - if (!context) - return nullptr; - if (resourceString.toLower() == "nsopenglcontext") - return nsOpenGLContextForContext(context); - if (resourceString.toLower() == "cglcontextobj") - return cglContextForContext(context); - - return nullptr; -} -#endif - void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) { if (!window->handle()) @@ -182,25 +168,6 @@ void QCocoaNativeInterface::onAppFocusWindowChanged(QWindow *window) QCocoaMenuBar::updateMenuBarImmediately(); } -#ifndef QT_NO_OPENGL -void *QCocoaNativeInterface::cglContextForContext(QOpenGLContext* context) -{ - NSOpenGLContext *nsOpenGLContext = static_cast<NSOpenGLContext*>(nsOpenGLContextForContext(context)); - if (nsOpenGLContext) - return [nsOpenGLContext CGLContextObj]; - return nullptr; -} - -void *QCocoaNativeInterface::nsOpenGLContextForContext(QOpenGLContext* context) -{ - if (context) { - if (QCocoaGLContext *cocoaGLContext = static_cast<QCocoaGLContext *>(context->handle())) - return cocoaGLContext->nativeContext(); - } - return nullptr; -} -#endif - QFunctionPointer QCocoaNativeInterface::platformFunction(const QByteArray &function) const { if (function == QCocoaWindowFunctions::bottomLeftClippedByNSWindowOffsetIdentifier()) diff --git a/src/plugins/platforms/eglfs/api/qeglfscontext.cpp b/src/plugins/platforms/eglfs/api/qeglfscontext.cpp index 48fafbda8d..2dbf762cf4 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfscontext.cpp @@ -50,10 +50,9 @@ QT_BEGIN_NAMESPACE QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLConfig *config, const QVariant &nativeHandle) - : QEGLPlatformContext(format, share, display, config, nativeHandle, - qt_egl_device_integration()->supportsSurfacelessContexts() ? Flags() : QEGLPlatformContext::NoSurfaceless), - m_tempWindow(0) + EGLConfig *config) + : QEGLPlatformContext(format, share, display, config, + qt_egl_device_integration()->supportsSurfacelessContexts() ? Flags() : QEGLPlatformContext::NoSurfaceless) { } diff --git a/src/plugins/platforms/eglfs/api/qeglfscontext_p.h b/src/plugins/platforms/eglfs/api/qeglfscontext_p.h index af8725b6b3..f3b506ac7f 100644 --- a/src/plugins/platforms/eglfs/api/qeglfscontext_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfscontext_p.h @@ -61,8 +61,9 @@ QT_BEGIN_NAMESPACE class Q_EGLFS_EXPORT QEglFSContext : public QEGLPlatformContext { public: + using QEGLPlatformContext::QEGLPlatformContext; QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLConfig *config, const QVariant &nativeHandle); + EGLConfig *config); EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override; EGLSurface createTemporaryOffscreenSurface() override; void destroyTemporaryOffscreenSurface(EGLSurface surface) override; @@ -72,7 +73,7 @@ public: QEglFSCursorData cursorData; private: - EGLNativeWindowType m_tempWindow; + EGLNativeWindowType m_tempWindow = 0; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp index 9b479a21c1..c94a12a198 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp @@ -76,8 +76,6 @@ # include <QtOpenGL/private/qopenglcompositorbackingstore_p.h> #endif -#include <QtPlatformHeaders/QEGLNativeContext> - #if QT_CONFIG(libinput) #include <QtInputSupport/private/qlibinputhandler_p.h> #endif @@ -215,22 +213,20 @@ QPlatformOpenGLContext *QEglFSIntegration::createPlatformOpenGLContext(QOpenGLCo { EGLDisplay dpy = context->screen() ? static_cast<QEglFSScreen *>(context->screen()->handle())->display() : display(); QPlatformOpenGLContext *share = context->shareHandle(); - QVariant nativeHandle = context->nativeHandle(); QEglFSContext *ctx; QSurfaceFormat adjustedFormat = qt_egl_device_integration()->surfaceFormatFor(context->format()); - if (nativeHandle.isNull()) { - EGLConfig config = QEglFSDeviceIntegration::chooseConfig(dpy, adjustedFormat); - ctx = new QEglFSContext(adjustedFormat, share, dpy, &config, QVariant()); - } else { - ctx = new QEglFSContext(adjustedFormat, share, dpy, nullptr, nativeHandle); - } - nativeHandle = QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(ctx->eglContext(), dpy)); + EGLConfig config = QEglFSDeviceIntegration::chooseConfig(dpy, adjustedFormat); + ctx = new QEglFSContext(adjustedFormat, share, dpy, &config); - context->setNativeHandle(nativeHandle); return ctx; } +QOpenGLContext *QEglFSIntegration::createOpenGLContext(EGLContext context, EGLDisplay contextDisplay, QOpenGLContext *shareContext) const +{ + return QEGLPlatformContext::createFrom<QEglFSContext>(context, contextDisplay, display(), shareContext); +} + QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const { EGLDisplay dpy = surface->screen() ? static_cast<QEglFSScreen *>(surface->screen()->handle())->display() : display(); diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h index 7df1aa3c2c..baf9baadda 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h @@ -57,6 +57,7 @@ #include <QtGui/QWindow> #include <qpa/qplatformintegration.h> #include <qpa/qplatformnativeinterface.h> +#include <qpa/qplatformopenglcontext.h> #include <qpa/qplatformscreen.h> QT_BEGIN_NAMESPACE @@ -67,6 +68,7 @@ class QFbVtHandler; class QEvdevKeyboardManager; class Q_EGLFS_EXPORT QEglFSIntegration : public QPlatformIntegration, public QPlatformNativeInterface + , public QPlatformInterface::Private::QEGLIntegration { public: QEglFSIntegration(); @@ -86,6 +88,7 @@ public: QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override; #ifndef QT_NO_OPENGL QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; + QOpenGLContext *createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const override; QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override; #endif #if QT_CONFIG(vulkan) diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp index 84991d751f..53ec3e80c2 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp @@ -41,7 +41,6 @@ #include <QByteArray> #include <QOpenGLContext> -#include <QtPlatformHeaders/QGLXNativeContext> #include <X11/Xlib.h> #include <GL/glx.h> @@ -241,9 +240,6 @@ QOffscreenX11GLXContext::QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGL d->window = createDummyWindow(x11, visualInfo); XFree(visualInfo); } - if (d->context) - context->setNativeHandle(QVariant::fromValue<QGLXNativeContext>(QGLXNativeContext(d->context))); - } QOffscreenX11GLXContext::~QOffscreenX11GLXContext() @@ -296,7 +292,7 @@ bool QOffscreenX11GLXContext::isValid() const return d->context && d->window; } -void *QOffscreenX11GLXContext::glxContext() const +GLXContext QOffscreenX11GLXContext::glxContext() const { return d->context; } diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h index 5ef51a15a8..005ac26151 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h +++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h @@ -90,6 +90,7 @@ private: class QOffscreenX11GLXContextData; class QOffscreenX11GLXContext : public QPlatformOpenGLContext + , public QPlatformInterface::QGLXContext { public: QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGLContext *context); @@ -104,8 +105,10 @@ public: bool isSharing() const override; bool isValid() const override; + GLXContext nativeContext() const override { return glxContext(); } + void *glxConfig() const; - void *glxContext() const; + GLXContext glxContext() const; private: QScopedPointer<QOffscreenX11GLXContextData> d; diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index c1921810e7..aa93b85289 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -46,7 +46,6 @@ #include <QtCore/qsysinfo.h> #include <QtGui/qguiapplication.h> #include <qpa/qplatformnativeinterface.h> -#include <QtPlatformHeaders/qwglnativecontext.h> #include <algorithm> @@ -225,6 +224,11 @@ QWindowsOpenGLContext *QOpenGLStaticContext::createContext(QOpenGLContext *conte return new QWindowsGLContext(this, context); } +QWindowsOpenGLContext *QOpenGLStaticContext::createContext(HGLRC context, HWND window) +{ + return new QWindowsGLContext(this, context, window); +} + template <class MaskType, class FlagType> inline bool testFlag(MaskType mask, FlagType flag) { return (mask & MaskType(flag)) != 0; @@ -1056,48 +1060,6 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, if (!m_staticContext) // Something went very wrong. Stop here, isValid() will return false. return; - QVariant nativeHandle = context->nativeHandle(); - if (!nativeHandle.isNull()) { - // Adopt and existing context. - if (!nativeHandle.canConvert<QWGLNativeContext>()) { - qWarning("QWindowsGLContext: Requires a QWGLNativeContext"); - return; - } - auto handle = nativeHandle.value<QWGLNativeContext>(); - HGLRC wglcontext = handle.context(); - HWND wnd = handle.window(); - if (!wglcontext || !wnd) { - qWarning("QWindowsGLContext: No context and window given"); - return; - } - - HDC dc = GetDC(wnd); - // A window with an associated pixel format is mandatory. - // When no SetPixelFormat() call has been made, the following will fail. - m_pixelFormat = GetPixelFormat(dc); - bool ok = m_pixelFormat != 0; - if (!ok) - qWarning("QWindowsGLContext: Failed to get pixel format"); - ok = DescribePixelFormat(dc, m_pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &m_obtainedPixelFormatDescriptor); - if (!ok) { - qWarning("QWindowsGLContext: Failed to describe pixel format"); - } else { - QWindowsOpenGLAdditionalFormat obtainedAdditional; - m_obtainedFormat = GDI::qSurfaceFormatFromPixelFormat(m_obtainedPixelFormatDescriptor, &obtainedAdditional); - m_renderingContext = wglcontext; - ok = updateObtainedParams(dc); - } - - ReleaseDC(wnd, dc); - - if (ok) - m_ownsContext = false; - else - m_renderingContext = nullptr; - - return; - } - QSurfaceFormat format = context->format(); if (format.renderableType() == QSurfaceFormat::DefaultRenderableType) format.setRenderableType(QSurfaceFormat::OpenGL); @@ -1199,11 +1161,6 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, } while (false); - // Make the HGLRC retrievable via QOpenGLContext::nativeHandle(). - // Do not provide the window since it is the dummy one and it is about to disappear. - if (m_renderingContext) - context->setNativeHandle(QVariant::fromValue<QWGLNativeContext>(QWGLNativeContext(m_renderingContext, nullptr))); - if (hdc) ReleaseDC(dummyWindow, hdc); if (dummyWindow) @@ -1217,6 +1174,37 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, << "\n HGLRC=" << m_renderingContext; } +QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, HGLRC wglcontext, HWND wnd) + : m_staticContext(staticContext) +{ + if (!m_staticContext) // Something went very wrong. Stop here, isValid() will return false. + return; + + HDC dc = GetDC(wnd); + // A window with an associated pixel format is mandatory. + // When no SetPixelFormat() call has been made, the following will fail. + m_pixelFormat = GetPixelFormat(dc); + bool ok = m_pixelFormat != 0; + if (!ok) + qWarning("QWindowsGLContext: Failed to get pixel format"); + ok = DescribePixelFormat(dc, m_pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &m_obtainedPixelFormatDescriptor); + if (!ok) { + qWarning("QWindowsGLContext: Failed to describe pixel format"); + } else { + QWindowsOpenGLAdditionalFormat obtainedAdditional; + m_obtainedFormat = GDI::qSurfaceFormatFromPixelFormat(m_obtainedPixelFormatDescriptor, &obtainedAdditional); + m_renderingContext = wglcontext; + ok = updateObtainedParams(dc); + } + + ReleaseDC(wnd, dc); + + if (ok) + m_ownsContext = false; + else + m_renderingContext = nullptr; +} + QWindowsGLContext::~QWindowsGLContext() { if (m_renderingContext && m_ownsContext) diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h index 608cc9cfea..2970f3d333 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.h +++ b/src/plugins/platforms/windows/qwindowsglcontext.h @@ -174,6 +174,7 @@ public: static QByteArray getGlString(unsigned int which); QWindowsOpenGLContext *createContext(QOpenGLContext *context) override; + QWindowsOpenGLContext *createContext(HGLRC context, HWND window) override; void *moduleHandle() const override { return opengl32.moduleHandle(); } QOpenGLContext::OpenGLModuleType moduleType() const override { return QOpenGLContext::LibGL; } @@ -199,10 +200,12 @@ public: static QWindowsOpengl32DLL opengl32; }; -class QWindowsGLContext : public QWindowsOpenGLContext +class QWindowsGLContext : public QWindowsOpenGLContext, public QPlatformInterface::QWGLContext { public: explicit QWindowsGLContext(QOpenGLStaticContext *staticContext, QOpenGLContext *context); + explicit QWindowsGLContext(QOpenGLStaticContext *staticContext, HGLRC context, HWND window); + ~QWindowsGLContext() override; bool isSharing() const override { return context()->shareHandle(); } bool isValid() const override { return m_renderingContext && !m_lost; } @@ -219,7 +222,7 @@ public: HGLRC renderingContext() const { return m_renderingContext; } - void *nativeContext() const override { return m_renderingContext; } + HGLRC nativeContext() const override { return m_renderingContext; } private: typedef GLenum (APIENTRY *GlGetGraphicsResetStatusArbType)(); diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 96abfe5b01..ea077bc695 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -475,6 +475,33 @@ QOpenGLContext::OpenGLModuleType QWindowsIntegration::openGLModuleType() #endif } +HMODULE QWindowsIntegration::openGLModuleHandle() const +{ + if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) + return static_cast<HMODULE>(staticOpenGLContext->moduleHandle()); + + return nullptr; +} + +QOpenGLContext *QWindowsIntegration::createOpenGLContext(HGLRC ctx, HWND window, QOpenGLContext *shareContext) const +{ + if (!ctx || !window) + return nullptr; + + if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) { + QScopedPointer<QWindowsOpenGLContext> result(staticOpenGLContext->createContext(ctx, window)); + if (result->isValid()) { + auto *context = new QOpenGLContext; + context->setShareContext(shareContext); + auto *contextPrivate = QOpenGLContextPrivate::get(context); + contextPrivate->adopt(result.take()); + return context; + } + } + + return nullptr; +} + QWindowsStaticOpenGLContext *QWindowsIntegration::staticOpenGLContext() { QWindowsIntegration *integration = QWindowsIntegration::instance(); diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index 3c3763745c..348da5c58c 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -44,6 +44,8 @@ #include <qpa/qplatformintegration.h> #include <QtCore/qscopedpointer.h> #include <QtGui/private/qwindowsfontdatabase_p.h> +#include <QtGui/private/qopenglcontext_p.h> +#include <qpa/qplatformopenglcontext.h> QT_BEGIN_NAMESPACE @@ -52,7 +54,7 @@ struct QWindowsWindowData; class QWindowsWindow; class QWindowsStaticOpenGLContext; -class QWindowsIntegration : public QPlatformIntegration +class QWindowsIntegration : public QPlatformIntegration, public QPlatformInterface::Private::QWindowsGLIntegration { Q_DISABLE_COPY_MOVE(QWindowsIntegration) public: @@ -87,6 +89,9 @@ public: QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; QOpenGLContext::OpenGLModuleType openGLModuleType() override; static QWindowsStaticOpenGLContext *staticOpenGLContext(); + + HMODULE openGLModuleHandle() const override; + QOpenGLContext *createOpenGLContext(HGLRC context, HWND window, QOpenGLContext *shareContext) const; #endif QAbstractEventDispatcher *createEventDispatcher() const override; void initialize() override; diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h index 6d9c85f738..78ff23669c 100644 --- a/src/plugins/platforms/windows/qwindowsopenglcontext.h +++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h @@ -57,6 +57,7 @@ public: virtual ~QWindowsStaticOpenGLContext() = default; virtual QWindowsOpenGLContext *createContext(QOpenGLContext *context) = 0; + virtual QWindowsOpenGLContext *createContext(HGLRC context, HWND window) = 0; virtual void *moduleHandle() const = 0; virtual QOpenGLContext::OpenGLModuleType moduleType() const = 0; virtual bool supportsThreadedOpenGL() const { return false; } @@ -77,9 +78,6 @@ class QWindowsOpenGLContext : public QPlatformOpenGLContext { Q_DISABLE_COPY_MOVE(QWindowsOpenGLContext) public: - // Returns the native context handle (e.g. HGLRC for WGL). - virtual void *nativeContext() const = 0; - // These should be implemented only for some winsys interfaces, for example EGL. // For others, like WGL, they are not relevant. virtual void *nativeDisplay() const { return nullptr; } diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h index af394d12ed..a2d677a82f 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h @@ -43,16 +43,15 @@ #include "qxcbeglwindow.h" #include <QtEglSupport/private/qeglplatformcontext_p.h> #include <QtEglSupport/private/qeglpbuffer_p.h> -#include <QtPlatformHeaders/QEGLNativeContext> QT_BEGIN_NAMESPACE class QXcbEglContext : public QEGLPlatformContext { public: - QXcbEglContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share, - EGLDisplay display, const QVariant &nativeHandle) - : QEGLPlatformContext(glFormat, share, display, nullptr, nativeHandle) + using QEGLPlatformContext::QEGLPlatformContext; + QXcbEglContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share, EGLDisplay display) + : QEGLPlatformContext(glFormat, share, display, nullptr) { } @@ -86,10 +85,6 @@ public: else return static_cast<QEGLPbuffer *>(surface)->pbuffer(); } - - QVariant nativeHandle() const { - return QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(eglContext(), eglDisplay())); - } }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp index fe18bc24db..5f6c7bf903 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp @@ -101,12 +101,15 @@ QPlatformOpenGLContext *QXcbEglIntegration::createPlatformOpenGLContext(QOpenGLC QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle()); QXcbEglContext *platformContext = new QXcbEglContext(screen->surfaceFormatFor(context->format()), context->shareHandle(), - eglDisplay(), - context->nativeHandle()); - context->setNativeHandle(platformContext->nativeHandle()); + eglDisplay()); return platformContext; } +QOpenGLContext *QXcbEglIntegration::createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const +{ + return QEGLPlatformContext::createFrom<QXcbEglContext>(context, display, eglDisplay(), shareContext); +} + QPlatformOffscreenSurface *QXcbEglIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const { QXcbScreen *screen = static_cast<QXcbScreen *>(surface->screen()->handle()); diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h index 54a9f5cd83..ddb4488105 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h @@ -45,6 +45,7 @@ #include "qxcbeglwindow.h" #include <QtGui/QOpenGLContext> +#include <qpa/qplatformopenglcontext.h> #include <QtGui/qpa/qplatformscreen.h> #include <QtGui/QScreen> @@ -57,6 +58,7 @@ QT_BEGIN_NAMESPACE class QXcbEglNativeInterfaceHandler; class QXcbEglIntegration : public QXcbGlIntegration + , public QPlatformInterface::Private::QEGLIntegration { public: QXcbEglIntegration(); @@ -66,6 +68,7 @@ public: QXcbWindow *createWindow(QWindow *window) const override; QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; + QOpenGLContext *createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const override; QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override; bool supportsThreadedOpenGL() const override { return true; } diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index ca9cb4c86a..feae5fa13c 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -56,7 +56,6 @@ #include "qglxintegration.h" #include <QtGlxSupport/private/qglxconvenience_p.h> -#include <QtPlatformHeaders/QGLXNativeContext> #include "qxcbglintegration.h" @@ -219,26 +218,11 @@ static void updateFormatFromContext(QSurfaceFormat &format) } } -QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share, - const QVariant &nativeHandle) +QGLXContext::QGLXContext(Display *display, QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share) : QPlatformOpenGLContext() - , m_display(static_cast<Display *>(screen->connection()->xlib_display())) - , m_config(nullptr) - , m_context(nullptr) - , m_shareContext(nullptr) + , m_display(display) , m_format(format) - , m_isPBufferCurrent(false) - , m_ownsContext(nativeHandle.isNull()) - , m_getGraphicsResetStatus(nullptr) - , m_lost(false) -{ - if (nativeHandle.isNull()) - init(screen, share); - else - init(screen, share, nativeHandle); -} - -void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) + , m_ownsContext(true) { if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType) #if QT_CONFIG(opengles2) @@ -423,49 +407,15 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) XDestroyWindow(m_display, window); } -void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle) +QGLXContext::QGLXContext(Display *display, GLXContext context, void *visualInfo, QPlatformOpenGLContext *share) + : QPlatformOpenGLContext() + , m_display(display) { - if (!nativeHandle.canConvert<QGLXNativeContext>()) { - qWarning("QGLXContext: Requires a QGLXNativeContext"); - return; - } - QGLXNativeContext handle = qvariant_cast<QGLXNativeContext>(nativeHandle); - GLXContext context = handle.context(); - if (!context) { - qWarning("QGLXContext: No GLXContext given"); - return; - } + // Legacy contexts created using glXCreateContext are created using a + // XVisualInfo. If the user passed one we should use that. + XVisualInfo *vinfo = static_cast<XVisualInfo*>(visualInfo); - // Legacy contexts created using glXCreateContext are created using a visual - // and the FBConfig cannot be queried. The only way to adapt these contexts - // is to figure out the visual id. - XVisualInfo *vinfo = nullptr; - // If the VisualID is provided use it. - VisualID vid = handle.visualId(); - if (!vid) { - // In the absence of the VisualID figure it out from the window. - Window wnd = handle.window(); - if (wnd) { - XWindowAttributes attrs; - XGetWindowAttributes(m_display, wnd, &attrs); - vid = XVisualIDFromVisual(attrs.visual); - } - } - if (vid) { - XVisualInfo v; - v.screen = screen->screenNumber(); - v.visualid = vid; - int n = 0; - vinfo = XGetVisualInfo(m_display, VisualScreenMask | VisualIDMask, &v, &n); - if (n < 1) { - XFree(vinfo); - vinfo = nullptr; - } - } - - // For contexts created with an FBConfig using the modern functions providing the - // visual or window is not mandatory. Just query the config from the context. - GLXFBConfig config = nullptr; + // Otherwise assume the context was created with an FBConfig using the modern functions if (!vinfo) { int configId = 0; if (glXQueryContext(m_display, context, GLX_FBCONFIG_ID, &configId) != Success) { @@ -490,19 +440,17 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const if (configs && numConfigs > 1) // this is suspicious so warn but let it continue qWarning("QGLXContext: Multiple configs for FBConfig ID %d", configId); - config = configs[0]; - // Store the config. - m_config = config; + m_config = configs[0]; } - Q_ASSERT(vinfo || config); + Q_ASSERT(vinfo || m_config); int screenNumber = DefaultScreen(m_display); Window window; if (vinfo) window = createDummyWindow(m_display, vinfo, screenNumber, RootWindow(m_display, screenNumber)); else - window = createDummyWindow(m_display, config, screenNumber, RootWindow(m_display, screenNumber)); + window = createDummyWindow(m_display, m_config, screenNumber, RootWindow(m_display, screenNumber)); if (!window) { qWarning("QGLXContext: Failed to create dummy window"); return; @@ -522,7 +470,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const if (vinfo) qglx_surfaceFormatFromVisualInfo(&m_format, m_display, vinfo); else - qglx_surfaceFormatFromGLXFBConfig(&m_format, m_display, config); + qglx_surfaceFormatFromGLXFBConfig(&m_format, m_display, m_config); glXMakeCurrent(m_display, prevDrawable, prevContext); XDestroyWindow(m_display, window); @@ -553,11 +501,6 @@ static QXcbScreen *screenForPlatformSurface(QPlatformSurface *surface) return nullptr; } -QVariant QGLXContext::nativeHandle() const -{ - return QVariant::fromValue<QGLXNativeContext>(QGLXNativeContext(m_context)); -} - bool QGLXContext::makeCurrent(QPlatformSurface *surface) { bool success = false; diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h index 2a88fd6e59..a7468c8fac 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h @@ -53,11 +53,12 @@ QT_BEGIN_NAMESPACE -class QGLXContext : public QPlatformOpenGLContext +class QGLXContext : public QPlatformOpenGLContext, + public QPlatformInterface::QGLXContext { public: - QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share, - const QVariant &nativeHandle); + QGLXContext(Display *display, QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share); + QGLXContext(Display *display, GLXContext context, void *visualInfo, QPlatformOpenGLContext *share); ~QGLXContext(); bool makeCurrent(QPlatformSurface *surface) override; @@ -69,27 +70,24 @@ public: bool isSharing() const override; bool isValid() const override; + GLXContext nativeContext() const override { return glxContext(); } + GLXContext glxContext() const { return m_context; } GLXFBConfig glxConfig() const { return m_config; } - QVariant nativeHandle() const; - static bool supportsThreading(); static void queryDummyContext(); private: - void init(QXcbScreen *screen, QPlatformOpenGLContext *share); - void init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle); - - Display *m_display; - GLXFBConfig m_config; - GLXContext m_context; - GLXContext m_shareContext; + Display *m_display = nullptr; + GLXFBConfig m_config = nullptr; + GLXContext m_context = nullptr; + GLXContext m_shareContext = nullptr; QSurfaceFormat m_format; - bool m_isPBufferCurrent; - bool m_ownsContext; - GLenum (APIENTRY * m_getGraphicsResetStatus)(); - bool m_lost; + bool m_isPBufferCurrent = false; + bool m_ownsContext = false; + GLenum (APIENTRY * m_getGraphicsResetStatus)() = nullptr; + bool m_lost = false; static bool m_queriedDummyContext; static bool m_supportsThreading; }; diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp index 6814dbd844..733df7df51 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -49,6 +49,7 @@ #include "qglxintegration.h" #include <QtGui/QOpenGLContext> +#include <QtGui/private/qopenglcontext_p.h> #include "qxcbglxnativeinterfacehandler.h" @@ -187,10 +188,22 @@ QXcbWindow *QXcbGlxIntegration::createWindow(QWindow *window) const QPlatformOpenGLContext *QXcbGlxIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle()); - QGLXContext *platformContext = new QGLXContext(screen, screen->surfaceFormatFor(context->format()), - context->shareHandle(), context->nativeHandle()); - context->setNativeHandle(platformContext->nativeHandle()); - return platformContext; + return new QGLXContext(static_cast<Display *>(m_connection->xlib_display()), + screen, screen->surfaceFormatFor(context->format()), context->shareHandle()); +} + +QOpenGLContext *QXcbGlxIntegration::createOpenGLContext(GLXContext glxContext, void *visualInfo, QOpenGLContext *shareContext) const +{ + if (!glxContext) + return nullptr; + + QPlatformOpenGLContext *shareHandle = shareContext ? shareContext->handle() : nullptr; + + auto *context = new QOpenGLContext; + auto *contextPrivate = QOpenGLContextPrivate::get(context); + auto *display = static_cast<Display *>(m_connection->xlib_display()); + contextPrivate->adopt(new QGLXContext(display, glxContext, visualInfo, shareHandle)); + return context; } QPlatformOffscreenSurface *QXcbGlxIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.h index 26cb233a59..18c1be9489 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.h +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.h @@ -46,7 +46,8 @@ QT_BEGIN_NAMESPACE class QXcbNativeInterfaceHandler; -class QXcbGlxIntegration : public QXcbGlIntegration +class QXcbGlxIntegration : public QXcbGlIntegration, + public QPlatformInterface::Private::QGLXIntegration { public: QXcbGlxIntegration(); @@ -58,6 +59,7 @@ public: QXcbWindow *createWindow(QWindow *window) const override; QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override; + QOpenGLContext *createOpenGLContext(GLXContext context, void *visualInfo, QOpenGLContext *shareContext) const override; bool supportsThreadedOpenGL() const override; bool supportsSwitchableWidgetComposition() const override; diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index ff8b617d3a..fd64185852 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -275,7 +275,26 @@ QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLCont } return glIntegration->createPlatformOpenGLContext(context); } -#endif + +QOpenGLContext *QXcbIntegration::createOpenGLContext(GLXContext context, void *visualInfo, QOpenGLContext *shareContext) const +{ + using namespace QPlatformInterface::Private; + if (auto *glxIntegration = dynamic_cast<QGLXIntegration*>(m_connection->glIntegration())) + return glxIntegration->createOpenGLContext(context, visualInfo, shareContext); + else + return nullptr; +} + +QOpenGLContext *QXcbIntegration::createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const +{ + using namespace QPlatformInterface::Private; + if (auto *eglIntegration = dynamic_cast<QEGLIntegration*>(m_connection->glIntegration())) + return eglIntegration->createOpenGLContext(context, display, shareContext); + else + return nullptr; +} + +#endif // QT_NO_OPENGL QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *window) const { diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index a67e79e0b8..37d2db394c 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -43,6 +43,7 @@ #include <QtGui/private/qtguiglobal_p.h> #include <qpa/qplatformintegration.h> #include <qpa/qplatformscreen.h> +#include <qpa/qplatformopenglcontext.h> #include "qxcbexport.h" @@ -55,6 +56,8 @@ class QAbstractEventDispatcher; class QXcbNativeInterface; class Q_XCB_EXPORT QXcbIntegration : public QPlatformIntegration + , public QPlatformInterface::Private::QGLXIntegration + , public QPlatformInterface::Private::QEGLIntegration { public: QXcbIntegration(const QStringList ¶meters, int &argc, char **argv); @@ -65,6 +68,8 @@ public: QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override; #ifndef QT_NO_OPENGL QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; + QOpenGLContext *createOpenGLContext(GLXContext context, void *visualInfo, QOpenGLContext *shareContext) const override; + QOpenGLContext *createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext) const override; #endif QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override; diff --git a/tests/auto/gui/qopengl/tst_qopengl.cpp b/tests/auto/gui/qopengl/tst_qopengl.cpp index c093885951..b43defd2f3 100644 --- a/tests/auto/gui/qopengl/tst_qopengl.cpp +++ b/tests/auto/gui/qopengl/tst_qopengl.cpp @@ -52,15 +52,6 @@ #include <QSignalSpy> -#ifdef USE_GLX -// Must be included last due to the X11 types -#include <QtPlatformHeaders/QGLXNativeContext> -#endif - -#if defined(Q_OS_WIN32) && !QT_CONFIG(opengles2) -#include <QtPlatformHeaders/QWGLNativeContext> -#endif - Q_DECLARE_METATYPE(QImage::Format) class tst_QOpenGL : public QObject @@ -1480,6 +1471,8 @@ void tst_QOpenGL::defaultSurfaceFormat() QCOMPARE(context->format(), fmt); } +using namespace QPlatformInterface; + #ifdef USE_GLX void tst_QOpenGL::glxContextWrap() { @@ -1496,17 +1489,14 @@ void tst_QOpenGL::glxContextWrap() QOpenGLContext *ctx0 = new QOpenGLContext; ctx0->setFormat(window->format()); QVERIFY(ctx0->create()); - QVariant v = ctx0->nativeHandle(); - QVERIFY(!v.isNull()); - QVERIFY(v.canConvert<QGLXNativeContext>()); - GLXContext context = v.value<QGLXNativeContext>().context(); + auto *glxContextIf = ctx0->platformInterface<QGLXContext>(); + QVERIFY(glxContextIf); + GLXContext context = glxContextIf->nativeContext(); QVERIFY(context); // Then create another QOpenGLContext wrapping it. - QOpenGLContext *ctx = new QOpenGLContext; - ctx->setNativeHandle(QVariant::fromValue<QGLXNativeContext>(QGLXNativeContext(context))); - QVERIFY(ctx->create()); - QCOMPARE(ctx->nativeHandle().value<QGLXNativeContext>().context(), context); + QOpenGLContext *ctx = QGLXContext::fromNative(context); + QVERIFY(ctx); QVERIFY(nativeIf->nativeResourceForContext(QByteArrayLiteral("glxcontext"), ctx) == (void *) context); QVERIFY(ctx->makeCurrent(window)); @@ -1533,11 +1523,9 @@ void tst_QOpenGL::wglContextWrap() window->show(); QVERIFY(QTest::qWaitForWindowExposed(window.data())); - QVariant v = ctx->nativeHandle(); - QVERIFY(!v.isNull()); - QVERIFY(v.canConvert<QWGLNativeContext>()); - QWGLNativeContext nativeContext = v.value<QWGLNativeContext>(); - QVERIFY(nativeContext.context()); + auto *wglContext = ctx->platformInterface<QWGLContext>(); + QVERIFY(wglContext); + QVERIFY(wglContext->nativeContext()); // Now do a makeCurrent() do make sure the pixel format on the native // window (the HWND we are going to retrieve below) is set. @@ -1547,9 +1535,9 @@ void tst_QOpenGL::wglContextWrap() HWND wnd = (HWND) qGuiApp->platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("handle"), window.data()); QVERIFY(wnd); - QScopedPointer<QOpenGLContext> adopted(new QOpenGLContext); - adopted->setNativeHandle(QVariant::fromValue<QWGLNativeContext>(QWGLNativeContext(nativeContext.context(), wnd))); - QVERIFY(adopted->create()); + QScopedPointer<QOpenGLContext> adopted(QWGLContext::fromNative(wglContext->nativeContext(), wnd)); + QVERIFY(!adopted.isNull()); + QVERIFY(adopted->isValid()); // This tests two things: that a regular, non-adopted QOpenGLContext is // able to return a QSurfaceFormat containing the real values after diff --git a/tests/manual/qopenglcontext/qopenglcontext.pro b/tests/manual/qopenglcontext/qopenglcontext.pro index 08a9ab407c..06e2fc2e3b 100644 --- a/tests/manual/qopenglcontext/qopenglcontext.pro +++ b/tests/manual/qopenglcontext/qopenglcontext.pro @@ -1,7 +1,7 @@ TEMPLATE = app TARGET = qopenglcontext -QT += gui-private egl_support-private +QT += gui-private egl_support-private opengl HEADERS += $$PWD/qopenglcontextwindow.h diff --git a/tests/manual/qopenglcontext/qopenglcontextwindow.cpp b/tests/manual/qopenglcontext/qopenglcontextwindow.cpp index 0763d7244c..67898c0028 100644 --- a/tests/manual/qopenglcontext/qopenglcontextwindow.cpp +++ b/tests/manual/qopenglcontext/qopenglcontextwindow.cpp @@ -34,7 +34,6 @@ #include <qpa/qplatformnativeinterface.h> #include <QtEglSupport/private/qeglconvenience_p.h> -#include <QtPlatformHeaders/QEGLNativeContext> QOpenGLContextWindow::QOpenGLContextWindow() : m_blitter(0) @@ -98,7 +97,12 @@ void QOpenGLContextWindow::createForeignContext() // underlying native context. This way the texture, that belongs to the context // created here, will be accessible from m_context too. - EGLContext shareCtx = m_context->nativeHandle().value<QEGLNativeContext>().context(); + using namespace QPlatformInterface; + auto *eglContext = m_context->platformInterface<QEGLContext>(); + if (!eglContext) + qFatal("Not running with EGL backend"); + + EGLContext shareCtx = eglContext->nativeContext(); Q_ASSERT(shareCtx != EGL_NO_CONTEXT); EGLDisplay dpy = (EGLDisplay) qGuiApp->platformNativeInterface()->nativeResourceForWindow( @@ -127,12 +131,8 @@ void QOpenGLContextWindow::createForeignContext() Q_ASSERT(ctx != EGL_NO_CONTEXT); // Wrap ctx into a QOpenGLContext. - QOpenGLContext *ctxWrap = new QOpenGLContext; - ctxWrap->setNativeHandle(QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(ctx, dpy))); - ctxWrap->setShareContext(m_context); // only needed for correct bookkeeping - if (!ctxWrap->create()) - qFatal("Failed to created wrapping context"); - Q_ASSERT(ctxWrap->nativeHandle().value<QEGLNativeContext>().context() == ctx); + QOpenGLContext *ctxWrap = QEGLContext::fromNative(ctx, dpy, m_context); + Q_ASSERT(ctxWrap->platformInterface<QEGLContext>()->nativeContext() == ctx); QOffscreenSurface surface; surface.setFormat(fmt); diff --git a/tests/manual/qopenglcontext/qopenglcontextwindow.h b/tests/manual/qopenglcontext/qopenglcontextwindow.h index 37ff1b2082..1a497a750c 100644 --- a/tests/manual/qopenglcontext/qopenglcontextwindow.h +++ b/tests/manual/qopenglcontext/qopenglcontextwindow.h @@ -31,7 +31,7 @@ #include <QtGui/QWindow> #include <QtGui/QOpenGLContext> -#include <QtGui/QOpenGLTextureBlitter> +#include <QtOpenGL/QOpenGLTextureBlitter> #include <QtGui/QImage> #include <QtCore/QVariant> |