diff --git a/plugins/platforms/x11/standalone/glxbackend.cpp b/plugins/platforms/x11/standalone/glxbackend.cpp index e632109543..611d3e3996 100644 --- a/plugins/platforms/x11/standalone/glxbackend.cpp +++ b/plugins/platforms/x11/standalone/glxbackend.cpp @@ -212,6 +212,7 @@ void GlxBackend::init() m_haveMESACopySubBuffer = hasExtension(QByteArrayLiteral("GLX_MESA_copy_sub_buffer")); m_haveMESASwapControl = hasExtension(QByteArrayLiteral("GLX_MESA_swap_control")); m_haveEXTSwapControl = hasExtension(QByteArrayLiteral("GLX_EXT_swap_control")); + m_haveSGISwapControl = hasExtension(QByteArrayLiteral("GLX_SGI_swap_control")); // only enable Intel swap event if env variable is set, see BUG 342582 m_haveINTELSwapEvent = hasExtension(QByteArrayLiteral("GLX_INTEL_swap_event")) && qgetenv("KWIN_USE_INTEL_SWAP_EVENT") == QByteArrayLiteral("1"); @@ -221,7 +222,7 @@ void GlxBackend::init() glXSelectEvent(display(), glxWindow, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); } - haveSwapInterval = m_haveMESASwapControl || m_haveEXTSwapControl; + haveSwapInterval = m_haveMESASwapControl || m_haveEXTSwapControl || m_haveSGISwapControl; setSupportsBufferAge(false); @@ -233,15 +234,23 @@ void GlxBackend::init() } setSyncsToVBlank(false); - setBlocksForRetrace(true); + setBlocksForRetrace(false); + haveWaitSync = false; const bool wantSync = options->glPreferBufferSwap() != Options::NoSwapEncourage; if (wantSync && glXIsDirect(display(), ctx)) { if (haveSwapInterval) { // glXSwapInterval is preferred being more reliable setSwapInterval(1); setSyncsToVBlank(true); - } else { - qCWarning(KWIN_X11STANDALONE) << "NO VSYNC! glSwapInterval is not supported"; - } + } else if (hasExtension(QByteArrayLiteral("GLX_SGI_video_sync"))) { + unsigned int sync; + if (glXGetVideoSyncSGI(&sync) == 0 && glXWaitVideoSyncSGI(1, 0, &sync) == 0) { + setSyncsToVBlank(true); + setBlocksForRetrace(true); + haveWaitSync = true; + } else + qCWarning(KWIN_X11STANDALONE) << "NO VSYNC! glXSwapInterval is not supported, glXWaitVideoSync is supported but broken"; + } else + qCWarning(KWIN_X11STANDALONE) << "NO VSYNC! neither glSwapInterval nor glXWaitVideoSync are supported"; } else { // disable v-sync (if possible) setSwapInterval(0); @@ -678,6 +687,25 @@ void GlxBackend::setSwapInterval(int interval) glXSwapIntervalEXT(display(), glxWindow, interval); else if (m_haveMESASwapControl) glXSwapIntervalMESA(interval); + else if (m_haveSGISwapControl) + glXSwapIntervalSGI(interval); +} + +void GlxBackend::waitSync() +{ + // NOTE that vsync has no effect with indirect rendering + if (haveWaitSync) { + uint sync; +#if 0 + // TODO: why precisely is this important? + // the sync counter /can/ perform multiple steps during glXGetVideoSync & glXWaitVideoSync + // but this only leads to waiting for two frames??!? + glXGetVideoSync(&sync); + glXWaitVideoSync(2, (sync + 1) % 2, &sync); +#else + glXWaitVideoSyncSGI(1, 0, &sync); +#endif + } } void GlxBackend::present() @@ -696,6 +724,7 @@ void GlxBackend::present() if (haveSwapInterval) { glXSwapBuffers(display(), glxWindow); } else { + waitSync(); glXSwapBuffers(display(), glxWindow); } if (supportsBufferAge()) { diff --git a/plugins/platforms/x11/standalone/glxbackend.h b/plugins/platforms/x11/standalone/glxbackend.h index ec55ac49b1..33914337fb 100644 --- a/plugins/platforms/x11/standalone/glxbackend.h +++ b/plugins/platforms/x11/standalone/glxbackend.h @@ -86,6 +86,7 @@ private: bool initBuffer(); bool checkVersion(); void initExtensions(); + void waitSync(); bool initRenderingContext(); bool initFbConfig(); void initVisualDepthHashTable(); @@ -112,8 +113,10 @@ private: bool m_haveMESACopySubBuffer = false; bool m_haveMESASwapControl = false; bool m_haveEXTSwapControl = false; + bool m_haveSGISwapControl = false; bool m_haveINTELSwapEvent = false; bool haveSwapInterval = false; + bool haveWaitSync = false; Display *m_x11Display; friend class GlxTexture; };