summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changes-5.3.04
-rw-r--r--src/gui/kernel/qsurfaceformat.cpp49
-rw-r--r--src/gui/kernel/qsurfaceformat.h3
-rw-r--r--src/platformsupport/eglconvenience/qeglconvenience.cpp1
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp24
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext_p.h3
-rw-r--r--src/plugins/platforms/eglfs/qeglfscontext.cpp20
-rw-r--r--src/plugins/platforms/eglfs/qeglfscontext.h3
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp26
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h6
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp38
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp2
14 files changed, 144 insertions, 38 deletions
diff --git a/dist/changes-5.3.0 b/dist/changes-5.3.0
index 035d0656ed..7bcab28032 100644
--- a/dist/changes-5.3.0
+++ b/dist/changes-5.3.0
@@ -29,3 +29,7 @@ QtCore
QtGui
-----
+
+- Added setSwapInterval() to QSurfaceFormat. Platforms that support
+ setting the swap interval are now defaulting to the value of 1,
+ meaning vsync is enabled.
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);