diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/kernel/qsurfaceformat.cpp | 49 | ||||
-rw-r--r-- | src/gui/kernel/qsurfaceformat.h | 3 | ||||
-rw-r--r-- | src/platformsupport/eglconvenience/qeglconvenience.cpp | 1 | ||||
-rw-r--r-- | src/platformsupport/eglconvenience/qeglplatformcontext.cpp | 24 | ||||
-rw-r--r-- | src/platformsupport/eglconvenience/qeglplatformcontext_p.h | 3 | ||||
-rw-r--r-- | src/plugins/platforms/eglfs/qeglfscontext.cpp | 20 | ||||
-rw-r--r-- | src/plugins/platforms/eglfs/qeglfscontext.h | 3 | ||||
-rw-r--r-- | src/plugins/platforms/eglfs/qeglfswindow.cpp | 2 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsglcontext.cpp | 26 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsglcontext.h | 6 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qglxintegration.cpp | 38 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qglxintegration.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 2 |
13 files changed, 140 insertions, 38 deletions
diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp index ebfd71b4d3..b8fe55adc0 100644 --- a/src/gui/kernel/qsurfaceformat.cpp +++ b/src/gui/kernel/qsurfaceformat.cpp @@ -72,6 +72,7 @@ public: , profile(QSurfaceFormat::NoProfile) , major(2) , minor(0) + , swapInterval(1) // default to vsync { } @@ -89,7 +90,8 @@ public: renderableType(other->renderableType), profile(other->profile), major(other->major), - minor(other->minor) + minor(other->minor), + swapInterval(other->swapInterval) { } @@ -107,6 +109,7 @@ public: QSurfaceFormat::OpenGLContextProfile profile; int major; int minor; + int swapInterval; }; /*! @@ -676,6 +679,46 @@ void QSurfaceFormat::setVersion(int major, int minor) } /*! + Sets the preferred swap interval. The swap interval specifies the + minimum number of video frames that are displayed before a buffer + swap occurs. This can be used to sync the GL drawing into a window + to the vertical refresh of the screen. + + Setting an \a interval value of 0 will turn the vertical refresh + syncing off, any value higher than 0 will turn the vertical + syncing on. Setting \a interval to a higher value, for example 10, + results in having 10 vertical retraces between every buffer swap. + + The default interval is 1. + + Changing the swap interval may not be supported by the underlying + platform. In this case, the request will be silently ignored. + + \since 5.3 + + \sa swapInterval() + */ +void QSurfaceFormat::setSwapInterval(int interval) +{ + if (d->swapInterval != interval) { + detach(); + d->swapInterval = interval; + } +} + +/*! + Returns the swap interval. + + \since 5.3 + + \sa setSwapInterval() +*/ +int QSurfaceFormat::swapInterval() const +{ + return d->swapInterval; +} + +/*! Returns \c true if all the options of the two QSurfaceFormat objects \a a and \a b are equal. @@ -694,7 +737,8 @@ bool operator==(const QSurfaceFormat& a, const QSurfaceFormat& b) && a.d->swapBehavior == b.d->swapBehavior && a.d->profile == b.d->profile && a.d->major == b.d->major - && a.d->minor == b.d->minor); + && a.d->minor == b.d->minor + && a.d->swapInterval == b.d->swapInterval); } /*! @@ -724,6 +768,7 @@ QDebug operator<<(QDebug dbg, const QSurfaceFormat &f) << ", stencilBufferSize " << d->stencilSize << ", samples " << d->numSamples << ", swapBehavior " << d->swapBehavior + << ", swapInterval " << d->swapInterval << ", profile " << d->profile << ')'; diff --git a/src/gui/kernel/qsurfaceformat.h b/src/gui/kernel/qsurfaceformat.h index d182aa9f13..453beac5cd 100644 --- a/src/gui/kernel/qsurfaceformat.h +++ b/src/gui/kernel/qsurfaceformat.h @@ -135,6 +135,9 @@ public: bool testOption(FormatOption option) const; QSurfaceFormat::FormatOptions options() const; + int swapInterval() const; + void setSwapInterval(int interval); + private: QSurfaceFormatPrivate *d; diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp index b711a2aebd..50baf6f06d 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience.cpp +++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp @@ -350,6 +350,7 @@ QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, format.setStencilBufferSize(stencilSize); format.setSamples(sampleCount); format.setStereo(false); // EGL doesn't support stereo buffers + format.setSwapInterval(referenceFormat.swapInterval()); // Clear the EGL error state because some of the above may // have errored out because the attribute is not applicable diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 34ba21afdc..2bfa7a8a02 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -64,6 +64,9 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform : m_eglDisplay(display) , m_eglApi(eglApi) , m_eglConfig(q_configFromGLFormat(display, format)) + , m_swapInterval(-1) + , m_swapIntervalEnvChecked(false) + , m_swapIntervalFromEnv(-1) { init(format, share); } @@ -136,6 +139,27 @@ bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface) } #endif + + if (ok) { + if (!m_swapIntervalEnvChecked) { + m_swapIntervalEnvChecked = true; + if (qEnvironmentVariableIsSet("QT_QPA_EGL_SWAPINTERVAL")) { + QByteArray swapIntervalString = qgetenv("QT_QPA_EGL_SWAPINTERVAL"); + bool ok; + const int swapInterval = swapIntervalString.toInt(&ok); + if (ok) + m_swapIntervalFromEnv = swapInterval; + } + } + const int requestedSwapInterval = m_swapIntervalFromEnv >= 0 + ? m_swapIntervalFromEnv + : surface->format().swapInterval(); + if (requestedSwapInterval >= 0 && m_swapInterval != requestedSwapInterval) { + m_swapInterval = requestedSwapInterval; + eglSwapInterval(eglDisplay(), m_swapInterval); + } + } + return ok; } diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h index 952f5a856a..3d81a1c56e 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h @@ -80,6 +80,9 @@ private: EGLenum m_eglApi; EGLConfig m_eglConfig; QSurfaceFormat m_format; + int m_swapInterval; + bool m_swapIntervalEnvChecked; + int m_swapIntervalFromEnv; }; #endif //QEGLPLATFORMCONTEXT_H diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp index 2c6846132d..dd3f272d8b 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp @@ -54,29 +54,13 @@ QT_BEGIN_NAMESPACE QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLenum eglApi) : QEGLPlatformContext(QEglFSHooks::hooks()->surfaceFormatFor(format), share, display, - QEglFSIntegration::chooseConfig(display, QEglFSHooks::hooks()->surfaceFormatFor(format)), eglApi), - m_swapIntervalSet(false) + QEglFSIntegration::chooseConfig(display, QEglFSHooks::hooks()->surfaceFormatFor(format)), eglApi) { } bool QEglFSContext::makeCurrent(QPlatformSurface *surface) { - bool success = QEGLPlatformContext::makeCurrent(surface); - - if (success && !m_swapIntervalSet) { - m_swapIntervalSet = true; - int swapInterval = 1; - QByteArray swapIntervalString = qgetenv("QT_QPA_EGLFS_SWAPINTERVAL"); - if (!swapIntervalString.isEmpty()) { - bool ok; - swapInterval = swapIntervalString.toInt(&ok); - if (!ok) - swapInterval = 1; - } - eglSwapInterval(eglDisplay(), swapInterval); - } - - return success; + return QEGLPlatformContext::makeCurrent(surface); } EGLSurface QEglFSContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) diff --git a/src/plugins/platforms/eglfs/qeglfscontext.h b/src/plugins/platforms/eglfs/qeglfscontext.h index 8db340252c..6caa49ab4f 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.h +++ b/src/plugins/platforms/eglfs/qeglfscontext.h @@ -55,9 +55,6 @@ public: bool makeCurrent(QPlatformSurface *surface); EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface); void swapBuffers(QPlatformSurface *surface); - -private: - bool m_swapIntervalSet; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 70f0e437b2..d6f233b6c5 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -126,7 +126,7 @@ void QEglFSWindow::create() EGLDisplay display = static_cast<QEglFSScreen *>(screen)->display(); QSurfaceFormat platformFormat = QEglFSHooks::hooks()->surfaceFormatFor(window()->requestedFormat()); m_config = QEglFSIntegration::chooseConfig(display, platformFormat); - m_format = q_glFormatFromConfig(display, m_config); + m_format = q_glFormatFromConfig(display, m_config, platformFormat); resetSurface(); diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index d1ede39549..93f2b53672 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -880,7 +880,9 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex m_staticContext(staticContext), m_context(context), m_renderingContext(0), - m_pixelFormat(0), m_extensionsUsed(false) + m_pixelFormat(0), + m_extensionsUsed(false), + m_swapInterval(-1) { QSurfaceFormat format = context->format(); if (format.renderableType() == QSurfaceFormat::DefaultRenderableType) @@ -977,11 +979,9 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex QWindowsOpenGLContextFormat::current().apply(&m_obtainedFormat); - if (requestedAdditional.swapInterval != -1 && m_staticContext->wglSwapInternalExt) { - m_staticContext->wglSwapInternalExt(requestedAdditional.swapInterval); - if (m_staticContext->wglGetSwapInternalExt) - obtainedSwapInternal = m_staticContext->wglGetSwapInternalExt(); - } + if (m_staticContext->wglGetSwapInternalExt) + obtainedSwapInternal = m_staticContext->wglGetSwapInternalExt(); + wglMakeCurrent(0, 0); } while (false); if (hdc) @@ -1085,7 +1085,19 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface) window->setFlag(QWindowsWindow::OpenGLDoubleBuffered); } m_windowContexts.append(newContext); - return wglMakeCurrent(newContext.hdc, newContext.renderingContext); + + bool success = wglMakeCurrent(newContext.hdc, newContext.renderingContext); + + // Set the swap interval + if (m_staticContext->wglSwapInternalExt) { + const int interval = surface->format().swapInterval(); + if (interval >= 0 && m_swapInterval != interval) { + m_swapInterval = interval; + m_staticContext->wglSwapInternalExt(interval); + } + } + + return success; } void QWindowsGLContext::doneCurrent() diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h index 730e90bf70..c6b477128a 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.h +++ b/src/plugins/platforms/windows/qwindowsglcontext.h @@ -64,11 +64,10 @@ enum QWindowsGLFormatFlags // Additional format information for Windows. struct QWindowsOpenGLAdditionalFormat { - QWindowsOpenGLAdditionalFormat(unsigned formatFlagsIn = 0, unsigned pixmapDepthIn = 0, unsigned swapIntervalIn = -1) : - formatFlags(formatFlagsIn), pixmapDepth(pixmapDepthIn), swapInterval(swapIntervalIn) {} + QWindowsOpenGLAdditionalFormat(unsigned formatFlagsIn = 0, unsigned pixmapDepthIn = 0) : + formatFlags(formatFlagsIn), pixmapDepth(pixmapDepthIn) { } unsigned formatFlags; // QWindowsGLFormatFlags. unsigned pixmapDepth; // for QWindowsGLRenderToPixmap - int swapInterval; }; // Per-window data for active OpenGL contexts. @@ -178,6 +177,7 @@ private: PIXELFORMATDESCRIPTOR m_obtainedPixelFormatDescriptor; int m_pixelFormat; bool m_extensionsUsed; + int m_swapInterval; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index cbfbdf495f..5fc5b4ba97 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -167,6 +167,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat , m_shareContext(0) , m_format(format) , m_isPBufferCurrent(false) + , m_swapInterval(-1) { if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType) m_format.setRenderableType(QSurfaceFormat::OpenGL); @@ -326,19 +327,50 @@ QGLXContext::~QGLXContext() bool QGLXContext::makeCurrent(QPlatformSurface *surface) { + bool success = false; Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface); + Display *dpy = DISPLAY_FROM_XCB(m_screen); + GLXDrawable glxDrawable = 0; QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass(); if (surfaceClass == QSurface::Window) { m_isPBufferCurrent = false; QXcbWindow *window = static_cast<QXcbWindow *>(surface); - return glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), window->xcb_window(), m_context); + glxDrawable = window->xcb_window(); + success = glXMakeCurrent(dpy, glxDrawable, m_context); } else if (surfaceClass == QSurface::Offscreen) { m_isPBufferCurrent = true; QGLXPbuffer *pbuffer = static_cast<QGLXPbuffer *>(surface); - return glXMakeContextCurrent(DISPLAY_FROM_XCB(m_screen), pbuffer->pbuffer(), pbuffer->pbuffer(), m_context); + glxDrawable = pbuffer->pbuffer(); + success = glXMakeContextCurrent(dpy, glxDrawable, glxDrawable, m_context); + } + + if (success) { + int interval = surface->format().swapInterval(); + if (interval >= 0 && m_swapInterval != interval) { + m_swapInterval = interval; + typedef void (*qt_glXSwapIntervalEXT)(Display *, GLXDrawable, int); + typedef void (*qt_glXSwapIntervalMESA)(unsigned int); + static qt_glXSwapIntervalEXT glXSwapIntervalEXT = 0; + static qt_glXSwapIntervalMESA glXSwapIntervalMESA = 0; + static bool resolved = false; + if (!resolved) { + resolved = true; + QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(dpy, + m_screen->screenNumber())).split(' '); + if (glxExt.contains("GLX_EXT_swap_control")) + glXSwapIntervalEXT = (qt_glXSwapIntervalEXT) getProcAddress("glXSwapIntervalEXT"); + if (glxExt.contains("GLX_MESA_swap_control")) + glXSwapIntervalMESA = (qt_glXSwapIntervalMESA) getProcAddress("glXSwapIntervalMESA"); + } + if (glXSwapIntervalEXT) + glXSwapIntervalEXT(dpy, glxDrawable, interval); + else if (glXSwapIntervalMESA) + glXSwapIntervalMESA(interval); + } } - return false; + + return success; } void QGLXContext::doneCurrent() diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h index 7116b2389d..1666f71060 100644 --- a/src/plugins/platforms/xcb/qglxintegration.h +++ b/src/plugins/platforms/xcb/qglxintegration.h @@ -78,6 +78,7 @@ private: GLXContext m_shareContext; QSurfaceFormat m_format; bool m_isPBufferCurrent; + int m_swapInterval; }; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index aa53093868..832f871bb7 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -293,7 +293,7 @@ void QXcbWindow::create() #elif defined(XCB_USE_EGL) EGLDisplay eglDisplay = connection()->egl_display(); EGLConfig eglConfig = q_configFromGLFormat(eglDisplay, m_format, true); - m_format = q_glFormatFromConfig(eglDisplay, eglConfig); + m_format = q_glFormatFromConfig(eglDisplay, eglConfig, m_format); VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig); |