diff options
author | Laszlo Agocs <laszlo.agocs@digia.com> | 2014-09-01 10:43:42 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@digia.com> | 2014-09-01 14:10:12 +0200 |
commit | da2b3c4479e1d23ea6ead555cadc96a56967887a (patch) | |
tree | 20ebe47749dcf233f70f3db00d22125c41116e5c /src | |
parent | d06fb5609c02d639e44e932988f428c13aab71c3 (diff) |
Prevent current context from becoming inconsistent upon create()
Platform plugins have a tendency to make the newly created native
context current with a temporary surface. This is usually needed to
query some information related to the new context. Afterwards most of
them just reset to having nothing current.
This has two issues:
It unexpectedly changes the current context/surface. A call into
QOpenGLContext::create() does not imply that the current context will
get changed. This is the minor issue and we could probably live with
it (at least if it had been documented).
However, the real issue is that QOpenGLContext::currentContext() will
become inconsistent: it will still report whatever was current before
the create() even though on the EGL/WGL/GLX level that's not the case
anymore.
To prevent all this confusion the platform plugins can easily be
changed to restore whatever context/surface was current before they
altered it.
Change-Id: I6a5b4597c86571327524ddb13e0d02538593cc7b
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
Diffstat (limited to 'src')
4 files changed, 28 insertions, 7 deletions
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 148c5d9b2f..dce8bd888c 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -249,6 +249,15 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon void QEGLPlatformContext::updateFormatFromGL() { #ifndef QT_NO_OPENGL + // 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); + // Make the context current to ensure the GL version query works. This needs a surface too. const EGLint pbufferAttributes[] = { EGL_WIDTH, 1, @@ -300,7 +309,7 @@ void QEGLPlatformContext::updateFormatFromGL() } } } - eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext); } eglDestroySurface(m_eglDisplay, pbuffer); #endif // QT_NO_OPENGL diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index c62875d0ef..2d2d409a0f 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -512,6 +512,13 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext, if (pbuffer == EGL_NO_SURFACE) return; + 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); + if (QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, pbuffer, pbuffer, m_eglContext)) { const GLubyte *s = QWindowsEGLStaticContext::libGLESv2.glGetString(GL_VERSION); if (s) { @@ -524,7 +531,7 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext, } m_format.setProfile(QSurfaceFormat::NoProfile); m_format.setOptions(QSurfaceFormat::FormatOptions()); - QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + QWindowsEGLStaticContext::libEGL.eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext); } QWindowsEGLStaticContext::libEGL.eglDestroySurface(m_eglDisplay, pbuffer); } diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index e09018ef69..1ed27f545d 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -1207,6 +1207,9 @@ QWindowsGLContext::~QWindowsGLContext() bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval) { + HGLRC prevContext = wglGetCurrentContext(); + HDC prevSurface = wglGetCurrentDC(); + if (!QOpenGLStaticContext::opengl32.wglMakeCurrent(hdc, m_renderingContext)) { qWarning("Failed to make context current."); return false; @@ -1217,7 +1220,7 @@ bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval) if (m_staticContext->wglGetSwapInternalExt && obtainedSwapInterval) *obtainedSwapInterval = m_staticContext->wglGetSwapInternalExt(); - QOpenGLStaticContext::opengl32.wglMakeCurrent(0, 0); + QOpenGLStaticContext::opengl32.wglMakeCurrent(prevSurface, prevContext); return true; } diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index d6fe5f3477..3b13df863e 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -323,11 +323,11 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) // Query the OpenGL version and profile if (m_context && window) { + GLXContext prevContext = glXGetCurrentContext(); + GLXDrawable prevDrawable = glXGetCurrentDrawable(); glXMakeCurrent(DISPLAY_FROM_XCB(screen), window, m_context); updateFormatFromContext(m_format); - - // Make our context non-current - glXMakeCurrent(DISPLAY_FROM_XCB(screen), 0, 0); + glXMakeCurrent(DISPLAY_FROM_XCB(screen), prevDrawable, prevContext); } // Destroy our temporary window @@ -419,6 +419,8 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const } // Update OpenGL version and buffer sizes in our format. + GLXContext prevContext = glXGetCurrentContext(); + GLXDrawable prevDrawable = glXGetCurrentDrawable(); if (!glXMakeCurrent(dpy, window, context)) { qWarning("QGLXContext: Failed to make provided context current"); return; @@ -431,7 +433,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const qglx_surfaceFormatFromVisualInfo(&m_format, dpy, vinfo); else qglx_surfaceFormatFromGLXFBConfig(&m_format, dpy, config); - glXMakeCurrent(dpy, 0, 0); + glXMakeCurrent(dpy, prevDrawable, prevContext); XDestroyWindow(dpy, window); if (vinfo) |