summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@theqtcompany.com>2015-01-29 17:59:44 +0100
committerLaszlo Agocs <laszlo.agocs@theqtcompany.com>2015-02-02 14:03:24 +0000
commitd800180f828087e144b30346e8cea312aa2bf062 (patch)
treeecd87dedac480374ca17ac42e965f54934b22c90 /src
parent5382312e5c93c91be7e74e688331db0feeb438e7 (diff)
Utilize EGL_KHR_surfaceless_context in QOffscreenSurface when available
Use it also in the context initialization code which also relied on pbuffers until now. This is safe to do since QOffscreenSurface is deliberately kept minimal: we only support it for rendering to FBOs or uploading textures, it is quite useless for any rendering type of operation. Therefore simply not creating a surface when the extension is available is viable and should not break anything. While we should have done this a long time ago, the real inspiration now is to avoid crashes with some bad EGL implementations. Mesa in particular tends to crash in its interal configuration handling when trying to create a pbuffer surface with more exotic attributes, for example with multisampling enabled. Just getting rid of those properties is not an option since the resulting pbuffer would not be compatible with the existing context. Therefore our only option is to avoid the pbuffer altogether. There's a so-far-ignored patch for Mesa http://patchwork.freedesktop.org/patch/38100/ which tries to solve some of this but it turns out it is not sufficient to avoid problems with the multisampled case. So to avoid more headache, we just stop using pbuffers there. [ChangeLog][QtGui] QOffscreenSurface is now relying on EGL_KHR_surfaceless_context when available, and avoids creating a pbuffer surface when the extension is present. Change-Id: Id18742768b8e66c8d92ce65a9bf64b0296e14db7 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/gui/kernel/qoffscreensurface.cpp7
-rw-r--r--src/platformsupport/eglconvenience/qeglpbuffer.cpp6
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp24
3 files changed, 29 insertions, 8 deletions
diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp
index fb1dfd8df5..ed1b8d944a 100644
--- a/src/gui/kernel/qoffscreensurface.cpp
+++ b/src/gui/kernel/qoffscreensurface.cpp
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
QOffscreenSurface is intended to be used with QOpenGLContext to allow rendering with OpenGL in
an arbitrary thread without the need to create a QWindow.
- Even though the surface is renderable, the surface's pixels are not accessible.
+ Even though the surface is typically renderable, the surface's pixels are not accessible.
QOffscreenSurface should only be used to create OpenGL resources such as textures
or framebuffer objects.
@@ -77,6 +77,11 @@ QT_BEGIN_NAMESPACE
created}. Passing the format returned from QWindow::requestedFormat() to setFormat()
may result in an incompatible offscreen surface since the underlying windowing system
interface may offer a different set of configurations for window and pbuffer surfaces.
+
+ \note Some platforms may utilize a surfaceless context extension (for example
+ EGL_KHR_surfaceless_context) when available. In this case there will be no underlying
+ native surface. For the use cases of QOffscreenSurface (rendering to FBOs, texture
+ upload) this is not a problem.
*/
class Q_GUI_EXPORT QOffscreenSurfacePrivate : public QObjectPrivate
{
diff --git a/src/platformsupport/eglconvenience/qeglpbuffer.cpp b/src/platformsupport/eglconvenience/qeglpbuffer.cpp
index 2c6c332ac9..89f06ee3a9 100644
--- a/src/platformsupport/eglconvenience/qeglpbuffer.cpp
+++ b/src/platformsupport/eglconvenience/qeglpbuffer.cpp
@@ -55,6 +55,9 @@ QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffs
, m_display(display)
, m_pbuffer(EGL_NO_SURFACE)
{
+ if (q_hasEglExtension(display, "EGL_KHR_surfaceless_context"))
+ return;
+
EGLConfig config = q_configFromGLFormat(m_display, m_format, false, EGL_PBUFFER_BIT);
if (config) {
@@ -74,7 +77,8 @@ QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffs
QEGLPbuffer::~QEGLPbuffer()
{
- eglDestroySurface(m_display, m_pbuffer);
+ if (m_pbuffer != EGL_NO_SURFACE)
+ eglDestroySurface(m_display, m_pbuffer);
}
QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
index d7c4fd6764..984abe123f 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
@@ -278,7 +278,13 @@ void QEGLPlatformContext::updateFormatFromGL()
EGLSurface prevSurfaceDraw = eglGetCurrentSurface(EGL_DRAW);
EGLSurface prevSurfaceRead = eglGetCurrentSurface(EGL_READ);
- EGLSurface tempSurface = createTemporaryOffscreenSurface();
+ // Rely on the surfaceless extension, if available. This is beneficial since we can
+ // avoid creating an extra pbuffer surface which is apparently troublesome with some
+ // drivers (Mesa) when certain attributes are present (multisampling).
+ EGLSurface tempSurface = EGL_NO_SURFACE;
+ if (!q_hasEglExtension(m_eglDisplay, "EGL_KHR_surfaceless_context"))
+ tempSurface = createTemporaryOffscreenSurface();
+
if (eglMakeCurrent(m_eglDisplay, tempSurface, tempSurface, m_eglContext)) {
if (m_format.renderableType() == QSurfaceFormat::OpenGL
|| m_format.renderableType() == QSurfaceFormat::OpenGLES) {
@@ -316,8 +322,11 @@ void QEGLPlatformContext::updateFormatFromGL()
}
}
eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext);
+ } else {
+ qWarning("QEGLPlatformContext: Failed to make temporary surface current, format not updated");
}
- destroyTemporaryOffscreenSurface(tempSurface);
+ if (tempSurface != EGL_NO_SURFACE)
+ destroyTemporaryOffscreenSurface(tempSurface);
#endif // QT_NO_OPENGL
}
@@ -354,7 +363,8 @@ bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface)
: surface->format().swapInterval();
if (requestedSwapInterval >= 0 && m_swapInterval != requestedSwapInterval) {
m_swapInterval = requestedSwapInterval;
- eglSwapInterval(eglDisplay(), m_swapInterval);
+ if (eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context
+ eglSwapInterval(eglDisplay(), m_swapInterval);
}
} else {
qWarning("QEGLPlatformContext: eglMakeCurrent failed: %x", eglGetError());
@@ -383,9 +393,11 @@ void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface)
{
eglBindAPI(m_api);
EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
- bool ok = eglSwapBuffers(m_eglDisplay, eglSurface);
- if (!ok)
- qWarning("QEGLPlatformContext: eglSwapBuffers failed: %x", eglGetError());
+ if (eglSurface != EGL_NO_SURFACE) { // skip if using surfaceless context
+ bool ok = eglSwapBuffers(m_eglDisplay, eglSurface);
+ if (!ok)
+ qWarning("QEGLPlatformContext: eglSwapBuffers failed: %x", eglGetError());
+ }
}
void (*QEGLPlatformContext::getProcAddress(const QByteArray &procName)) ()