diff options
author | Michal Klocek <michal.klocek@qt.io> | 2020-07-09 13:47:51 +0200 |
---|---|---|
committer | Michal Klocek <michal.klocek@qt.io> | 2020-08-05 20:04:44 +0200 |
commit | 447f4a2f80a8728e41a6f544339b51b3ab889f0a (patch) | |
tree | e6deaa0b80fe3da4dd2b8dc73c5be31e78f8b09f /src/hardwareintegration | |
parent | 30754a9f1d0b5d83c7198b8566a4ba401bed6e34 (diff) | |
download | qtwayland-447f4a2f80a8728e41a6f544339b51b3ab889f0a.tar.gz |
Make QWaylandGLContext a QEGLPlatformContext
Since 6ff7947 we have a new way of querying for native context.
Rewrite some methods to reuse base implementation.
[ChangeLog][Client] Using EGL_KHR_surfaceless_context when querying
the surface format, if not supported falling back to temporary wayland surface.
Change-Id: I276e4b1108a703fb3cf1587db007537e3f36b2fe
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/hardwareintegration')
-rw-r--r-- | src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp | 187 | ||||
-rw-r--r-- | src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h | 31 |
2 files changed, 47 insertions, 171 deletions
diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp index a4cbd0e6..c0c86a6d 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp @@ -226,100 +226,37 @@ public: int m_textureWrap; }; - - -QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *display, const QSurfaceFormat &format, QPlatformOpenGLContext *share) - : QPlatformOpenGLContext() - , m_eglDisplay(eglDisplay) - , m_display(display) +QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *display, + const QSurfaceFormat &fmt, QPlatformOpenGLContext *share) + : QEGLPlatformContext(fmt, share, eglDisplay), m_display(display) { - m_config = q_configFromGLFormat(m_eglDisplay, format); - m_format = q_glFormatFromConfig(m_eglDisplay, m_config, format); - m_shareEGLContext = share ? static_cast<QWaylandGLContext *>(share)->eglContext() : EGL_NO_CONTEXT; - - QList<EGLint> eglContextAttrs; - eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); - eglContextAttrs.append(format.majorVersion()); - const bool hasKHRCreateContext = q_hasEglExtension(m_eglDisplay, "EGL_KHR_create_context"); - if (hasKHRCreateContext) { - eglContextAttrs.append(EGL_CONTEXT_MINOR_VERSION_KHR); - eglContextAttrs.append(format.minorVersion()); - int flags = 0; - // The debug bit is supported both for OpenGL and OpenGL ES. - if (format.testOption(QSurfaceFormat::DebugContext)) - flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; - // The fwdcompat bit is only for OpenGL 3.0+. - if (m_format.renderableType() == QSurfaceFormat::OpenGL - && format.majorVersion() >= 3 - && !format.testOption(QSurfaceFormat::DeprecatedFunctions)) - flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; - if (flags) { - eglContextAttrs.append(EGL_CONTEXT_FLAGS_KHR); - eglContextAttrs.append(flags); - } - // Profiles are OpenGL only and mandatory in 3.2+. The value is silently ignored for < 3.2. - if (m_format.renderableType() == QSurfaceFormat::OpenGL) { - switch (format.profile()) { - case QSurfaceFormat::NoProfile: - break; - case QSurfaceFormat::CoreProfile: - eglContextAttrs.append(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR); - eglContextAttrs.append(EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR); - break; - case QSurfaceFormat::CompatibilityProfile: - eglContextAttrs.append(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR); - eglContextAttrs.append(EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR); - break; - } - } - } - eglContextAttrs.append(EGL_NONE); - - switch (m_format.renderableType()) { + switch (format().renderableType()) { case QSurfaceFormat::OpenVG: m_api = EGL_OPENVG_API; break; #ifdef EGL_VERSION_1_4 -# if !QT_CONFIG(opengles2) - case QSurfaceFormat::DefaultRenderableType: -# endif case QSurfaceFormat::OpenGL: m_api = EGL_OPENGL_API; break; -#endif - case QSurfaceFormat::OpenGLES: +#endif // EGL_VERSION_1_4 default: m_api = EGL_OPENGL_ES_API; break; } - eglBindAPI(m_api); - - m_context = eglCreateContext(m_eglDisplay, m_config, m_shareEGLContext, eglContextAttrs.constData()); - - if (m_context == EGL_NO_CONTEXT) { - m_context = eglCreateContext(m_eglDisplay, m_config, EGL_NO_CONTEXT, eglContextAttrs.constData()); - m_shareEGLContext = EGL_NO_CONTEXT; - } - - EGLint error = eglGetError(); - if (error != EGL_SUCCESS) { - qWarning("QWaylandGLContext: failed to create EGLContext, error=%x", error); - return; - } // Create an EGL context for the decorations blitter. By using a dedicated context we don't need to make sure to not // change the context state and we also use OpenGL ES 2 API independently to what the app is using to draw. QList<EGLint> eglDecorationsContextAttrs = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - m_decorationsContext = eglCreateContext(m_eglDisplay, m_config, m_context, eglDecorationsContextAttrs.constData()); + m_decorationsContext = eglCreateContext(eglDisplay, eglConfig(), eglContext(), + eglDecorationsContextAttrs.constData()); if (m_decorationsContext == EGL_NO_CONTEXT) qWarning("QWaylandGLContext: Failed to create the decorations EGLContext. Decorations will not be drawn."); EGLint a = EGL_MIN_SWAP_INTERVAL; EGLint b = EGL_MAX_SWAP_INTERVAL; - if (!eglGetConfigAttrib(m_eglDisplay, m_config, a, &a) || - !eglGetConfigAttrib(m_eglDisplay, m_config, b, &b) || - a > 0) { - m_supportNonBlockingSwap = false; + if (!eglGetConfigAttrib(eglDisplay, eglConfig(), a, &a) + || !eglGetConfigAttrib(eglDisplay, eglConfig(), b, &b) || a > 0) { + m_supportNonBlockingSwap = false; } { bool ok; @@ -332,76 +269,34 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *dis << "Subsurface rendering can be affected." << "It may also cause the event loop to freeze in some situations"; } - - updateGLFormat(); } -void QWaylandGLContext::updateGLFormat() +EGLSurface QWaylandGLContext::createTemporaryOffscreenSurface() { - // Have to save & restore to prevent QOpenGLContext::currentContext() from becoming - // inconsistent after QOpenGLContext::create(). - EGLDisplay prevDisplay = eglGetCurrentDisplay(); - if (prevDisplay == EGL_NO_DISPLAY) // when no context is current - prevDisplay = m_eglDisplay; - EGLContext prevContext = eglGetCurrentContext(); - EGLSurface prevSurfaceDraw = eglGetCurrentSurface(EGL_DRAW); - EGLSurface prevSurfaceRead = eglGetCurrentSurface(EGL_READ); - - wl_surface *wlSurface = m_display->createSurface(nullptr); - wl_egl_window *eglWindow = wl_egl_window_create(wlSurface, 1, 1); + m_wlSurface = m_display->createSurface(nullptr); + m_eglWindow = wl_egl_window_create(m_wlSurface, 1, 1); #if QT_CONFIG(egl_extension_platform_wayland) - EGLSurface eglSurface = eglCreatePlatformWindowSurface(m_eglDisplay, m_config, eglWindow, nullptr); + EGLSurface eglSurface = + eglCreatePlatformWindowSurface(eglDisplay(), eglConfig(), m_eglWindow, nullptr); #else - EGLSurface eglSurface = eglCreateWindowSurface(m_eglDisplay, m_config, eglWindow, nullptr); + EGLSurface eglSurface = eglCreateWindowSurface(eglDisplay(), eglConfig(), m_eglWindow, nullptr); #endif + return eglSurface; +} - if (eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_context)) { - if (m_format.renderableType() == QSurfaceFormat::OpenGL - || m_format.renderableType() == QSurfaceFormat::OpenGLES) { - const GLubyte *s = glGetString(GL_VERSION); - if (s) { - QByteArray version = QByteArray(reinterpret_cast<const char *>(s)); - int major, minor; - if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) { - m_format.setMajorVersion(major); - m_format.setMinorVersion(minor); - } - } - m_format.setProfile(QSurfaceFormat::NoProfile); - m_format.setOptions(QSurfaceFormat::FormatOptions()); - if (m_format.renderableType() == QSurfaceFormat::OpenGL) { - // Check profile and options. - if (m_format.majorVersion() < 3) { - m_format.setOption(QSurfaceFormat::DeprecatedFunctions); - } else { - GLint value = 0; - glGetIntegerv(GL_CONTEXT_FLAGS, &value); - if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)) - m_format.setOption(QSurfaceFormat::DeprecatedFunctions); - if (value & GL_CONTEXT_FLAG_DEBUG_BIT) - m_format.setOption(QSurfaceFormat::DebugContext); - if (m_format.version() >= qMakePair(3, 2)) { - value = 0; - glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value); - if (value & GL_CONTEXT_CORE_PROFILE_BIT) - m_format.setProfile(QSurfaceFormat::CoreProfile); - else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) - m_format.setProfile(QSurfaceFormat::CompatibilityProfile); - } - } - } - } - eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext); - } - eglDestroySurface(m_eglDisplay, eglSurface); - wl_egl_window_destroy(eglWindow); - wl_surface_destroy(wlSurface); +void QWaylandGLContext::destroyTemporaryOffscreenSurface(EGLSurface eglSurface) +{ + eglDestroySurface(eglDisplay(), eglSurface); + wl_egl_window_destroy(m_eglWindow); + m_eglWindow = nullptr; + wl_surface_destroy(m_wlSurface); + m_wlSurface = nullptr; } QWaylandGLContext::~QWaylandGLContext() { delete m_blitter; - eglDestroyContext(m_eglDisplay, m_context); + m_blitter = nullptr; } bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface) @@ -419,7 +314,7 @@ bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface) EGLSurface eglSurface = window->eglSurface(); if (!window->needToUpdateContentFBO() && (eglSurface != EGL_NO_SURFACE)) { - if (!eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_context)) { + if (!eglMakeCurrent(eglDisplay(), eglSurface, eglSurface, eglContext())) { qWarning("QWaylandGLContext::makeCurrent: eglError: %x, this: %p \n", eglGetError(), this); return false; } @@ -436,7 +331,7 @@ bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface) eglSurface = window->eglSurface(); } - if (!eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_context)) { + if (!eglMakeCurrent(eglDisplay(), eglSurface, eglSurface, eglContext())) { qWarning("QWaylandGLContext::makeCurrent: eglError: %x, this: %p \n", eglGetError(), this); window->setCanResize(true); return false; @@ -452,7 +347,7 @@ bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface) void QWaylandGLContext::doneCurrent() { - eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglMakeCurrent(eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } void QWaylandGLContext::swapBuffers(QPlatformSurface *surface) @@ -470,7 +365,7 @@ void QWaylandGLContext::swapBuffers(QPlatformSurface *surface) EGLContext currentContext = eglGetCurrentContext(); EGLSurface currentSurfaceDraw = eglGetCurrentSurface(EGL_DRAW); EGLSurface currentSurfaceRead = eglGetCurrentSurface(EGL_READ); - eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_decorationsContext); + eglMakeCurrent(eglDisplay(), eglSurface, eglSurface, m_decorationsContext); if (!m_blitter) m_blitter = new DecorationsBlitter(this); @@ -481,15 +376,15 @@ void QWaylandGLContext::swapBuffers(QPlatformSurface *surface) eglMakeCurrent(currentDisplay, currentSurfaceDraw, currentSurfaceRead, currentContext); } - int swapInterval = m_supportNonBlockingSwap ? 0 : m_format.swapInterval(); - eglSwapInterval(m_eglDisplay, swapInterval); - if (swapInterval == 0 && m_format.swapInterval() > 0) { + int swapInterval = m_supportNonBlockingSwap ? 0 : format().swapInterval(); + eglSwapInterval(eglDisplay(), swapInterval); + if (swapInterval == 0 && format().swapInterval() > 0) { // Emulating a blocking swap glFlush(); // Flush before waiting so we can swap more quickly when the frame event arrives window->waitForFrameSync(100); } window->handleUpdate(); - eglSwapBuffers(m_eglDisplay, eglSurface); + eglSwapBuffers(eglDisplay(), eglSurface); window->setCanResize(true); } @@ -499,16 +394,6 @@ GLuint QWaylandGLContext::defaultFramebufferObject(QPlatformSurface *surface) co return static_cast<QWaylandEglWindow *>(surface)->contentFBO(); } -bool QWaylandGLContext::isSharing() const -{ - return m_shareEGLContext != EGL_NO_CONTEXT; -} - -bool QWaylandGLContext::isValid() const -{ - return m_context != EGL_NO_CONTEXT; -} - QFunctionPointer QWaylandGLContext::getProcAddress(const char *procName) { QFunctionPointer proc = (QFunctionPointer) eglGetProcAddress(procName); @@ -517,9 +402,9 @@ QFunctionPointer QWaylandGLContext::getProcAddress(const char *procName) return proc; } -EGLConfig QWaylandGLContext::eglConfig() const +EGLSurface QWaylandGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) { - return m_config; + return static_cast<QWaylandEglWindow *>(surface)->eglSurface(); } } diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h index 46c7bb76..21dc6461 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h +++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h @@ -40,12 +40,12 @@ #ifndef QWAYLANDGLCONTEXT_H #define QWAYLANDGLCONTEXT_H -#include <QtWaylandClient/private/qwaylanddisplay_p.h> +#include "qwaylandeglinclude.h" //must be first +#include <QtWaylandClient/private/qwaylanddisplay_p.h> +#include <QtGui/private/qeglplatformcontext_p.h> #include <qpa/qplatformopenglcontext.h> -#include "qwaylandeglinclude.h" - QT_BEGIN_NAMESPACE class QOpenGLShaderProgram; @@ -57,12 +57,11 @@ class QWaylandWindow; class QWaylandGLWindowSurface; class DecorationsBlitter; -class QWaylandGLContext : public QPlatformOpenGLContext +class QWaylandGLContext : public QEGLPlatformContext { public: QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *display, const QSurfaceFormat &format, QPlatformOpenGLContext *share); ~QWaylandGLContext(); - void swapBuffers(QPlatformSurface *surface) override; bool makeCurrent(QPlatformSurface *surface) override; @@ -70,29 +69,21 @@ public: GLuint defaultFramebufferObject(QPlatformSurface *surface) const override; - bool isSharing() const override; - bool isValid() const override; - QFunctionPointer getProcAddress(const char *procName) override; - QSurfaceFormat format() const override { return m_format; } - - EGLConfig eglConfig() const; - EGLContext eglContext() const { return m_context; } +protected: + EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override; + EGLSurface createTemporaryOffscreenSurface() override; + void destroyTemporaryOffscreenSurface(EGLSurface surface) override; private: - void updateGLFormat(); - - EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; QWaylandDisplay *m_display = nullptr; - EGLContext m_context; - EGLContext m_shareEGLContext; EGLContext m_decorationsContext; - EGLConfig m_config; - QSurfaceFormat m_format; DecorationsBlitter *m_blitter = nullptr; - uint m_api; bool m_supportNonBlockingSwap = true; + EGLenum m_api; + wl_surface *m_wlSurface = nullptr; + wl_egl_window *m_eglWindow = nullptr; }; } |