summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2020-06-08 20:00:36 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2020-07-02 10:27:50 +0200
commit6ff79478a44fce12ca18832a56db4a370a9ff417 (patch)
tree2bcd7ab7bac46fe28e0828e0a704649bbc025e8f /src/gui/kernel
parent037dce81fc27ec241edb6829f6df41927b80666e (diff)
Introduce platform API abstraction for QOpenGLContext
The API is available by including qopenglcontext.h as usual, but scoped in the QPlatformInterface namespace. The namespace exposes platform specific type-safe interfaces that provide: a) Factory functions for adopting native contexts, e.g. QCocoaGLContext::fromNative(nsContext, shareContext); b) Access to underlying native handles, e.g. openGLContext->platformInterface<QCocoaGLContext>->nativeContext() c) Platform specific functionality, e.g. static QWGLContext::openGLModuleHandle() openGLContext->platformInterface<QEGLContext>->doSomething(); The platform interfaces live close to the classes they extend, removing the need for complex indirection and plumbing, and avoids kitchen-sink modules and APIs such as the extras modules, QPlatformFunctions, or QPlatformNativeInterface. In the case of QOpenGLContext these platform APIs are backed by the platform plugin, so dynamic_cast is used to ensure the platform plugin supports the requested interface, but this is and implementation detail. The interface APIs are agnostic to where the implementation lives, while still being available to the user as part of the APIs they extend/augment. The documentation will be restored when the dust settles. Task-number: QTBUG-80233 Change-Id: Iac612403383991c4b24064332542a6e4bcbb3293 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'src/gui/kernel')
-rw-r--r--src/gui/kernel/kernel.pri3
-rw-r--r--src/gui/kernel/qopenglcontext.cpp117
-rw-r--r--src/gui/kernel/qopenglcontext.h10
-rw-r--r--src/gui/kernel/qopenglcontext_p.h3
-rw-r--r--src/gui/kernel/qopenglcontext_platform.h109
-rw-r--r--src/gui/kernel/qplatformintegration.h31
-rw-r--r--src/gui/kernel/qplatformopenglcontext.h45
-rw-r--r--src/gui/kernel/qwindowdefs_win.h6
8 files changed, 226 insertions, 98 deletions
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