Changeset View
Changeset View
Standalone View
Standalone View
plugins/platforms/x11/standalone/glxbackend.cpp
Show First 20 Lines • Show All 105 Lines • ▼ Show 20 Line(s) | |||||
106 | GlxBackend::GlxBackend(Display *display) | 106 | GlxBackend::GlxBackend(Display *display) | ||
107 | : OpenGLBackend() | 107 | : OpenGLBackend() | ||
108 | , m_overlayWindow(kwinApp()->platform()->createOverlayWindow()) | 108 | , m_overlayWindow(kwinApp()->platform()->createOverlayWindow()) | ||
109 | , window(None) | 109 | , window(None) | ||
110 | , fbconfig(nullptr) | 110 | , fbconfig(nullptr) | ||
111 | , glxWindow(None) | 111 | , glxWindow(None) | ||
112 | , ctx(nullptr) | 112 | , ctx(nullptr) | ||
113 | , m_bufferAge(0) | 113 | , m_bufferAge(0) | ||
114 | , haveSwapInterval(false) | | |||
115 | , m_x11Display(display) | 114 | , m_x11Display(display) | ||
116 | { | 115 | { | ||
117 | // Ensures calls to glXSwapBuffers will always block until the next | 116 | // Ensures calls to glXSwapBuffers will always block until the next | ||
118 | // retrace when using the proprietary NVIDIA driver. This must be | 117 | // retrace when using the proprietary NVIDIA driver. This must be | ||
119 | // set before libGL.so is loaded. | 118 | // set before libGL.so is loaded. | ||
120 | setenv("__GL_MaxFramesAllowed", "1", true); | 119 | setenv("__GL_MaxFramesAllowed", "1", true); | ||
121 | 120 | | |||
122 | // Force initialization of GLX integration in the Qt's xcb backend | 121 | // Force initialization of GLX integration in the Qt's xcb backend | ||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Line(s) | 170 | { | |||
213 | m_haveINTELSwapEvent = hasExtension(QByteArrayLiteral("GLX_INTEL_swap_event")) | 212 | m_haveINTELSwapEvent = hasExtension(QByteArrayLiteral("GLX_INTEL_swap_event")) | ||
214 | && qgetenv("KWIN_USE_INTEL_SWAP_EVENT") == QByteArrayLiteral("1"); | 213 | && qgetenv("KWIN_USE_INTEL_SWAP_EVENT") == QByteArrayLiteral("1"); | ||
215 | 214 | | |||
216 | if (m_haveINTELSwapEvent) { | 215 | if (m_haveINTELSwapEvent) { | ||
217 | m_swapEventFilter = std::make_unique<SwapEventFilter>(window, glxWindow); | 216 | m_swapEventFilter = std::make_unique<SwapEventFilter>(window, glxWindow); | ||
218 | glXSelectEvent(display(), glxWindow, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); | 217 | glXSelectEvent(display(), glxWindow, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); | ||
219 | } | 218 | } | ||
220 | 219 | | |||
221 | haveSwapInterval = m_haveMESASwapControl || m_haveEXTSwapControl; | | |||
222 | | ||||
223 | setSupportsBufferAge(false); | 220 | setSupportsBufferAge(false); | ||
224 | 221 | | |||
225 | if (hasExtension(QByteArrayLiteral("GLX_EXT_buffer_age"))) { | 222 | if (hasExtension(QByteArrayLiteral("GLX_EXT_buffer_age"))) { | ||
226 | const QByteArray useBufferAge = qgetenv("KWIN_USE_BUFFER_AGE"); | 223 | const QByteArray useBufferAge = qgetenv("KWIN_USE_BUFFER_AGE"); | ||
227 | 224 | | |||
228 | if (useBufferAge != "0") | 225 | if (useBufferAge != "0") | ||
229 | setSupportsBufferAge(true); | 226 | setSupportsBufferAge(true); | ||
230 | } | 227 | } | ||
231 | 228 | | |||
232 | setSyncsToVBlank(false); | | |||
233 | setBlocksForRetrace(true); | 229 | setBlocksForRetrace(true); | ||
234 | const bool wantSync = options->glPreferBufferSwap() != Options::NoSwapEncourage; | 230 | | ||
235 | if (wantSync && glXIsDirect(display(), ctx)) { | 231 | if (m_haveEXTSwapControl) { | ||
236 | if (haveSwapInterval) { // glXSwapInterval is preferred being more reliable | 232 | glXSwapIntervalEXT(display(), glxWindow, 1); | ||
237 | setSwapInterval(1); | 233 | } else if (m_haveMESASwapControl) { | ||
238 | setSyncsToVBlank(true); | 234 | glXSwapIntervalMESA(1); | ||
239 | } else { | 235 | } else { | ||
240 | qCWarning(KWIN_X11STANDALONE) << "NO VSYNC! glSwapInterval is not supported"; | 236 | qCWarning(KWIN_X11STANDALONE) << "NO VSYNC! glSwapInterval is not supported"; | ||
241 | } | 237 | } | ||
242 | } else { | 238 | | ||
243 | // disable v-sync (if possible) | | |||
244 | setSwapInterval(0); | | |||
245 | } | | |||
246 | if (glPlatform->isVirtualBox()) { | 239 | if (glPlatform->isVirtualBox()) { | ||
247 | // VirtualBox does not support glxQueryDrawable | 240 | // VirtualBox does not support glxQueryDrawable | ||
248 | // this should actually be in kwinglutils_funcs, but QueryDrawable seems not to be provided by an extension | 241 | // this should actually be in kwinglutils_funcs, but QueryDrawable seems not to be provided by an extension | ||
249 | // and the GLPlatform has not been initialized at the moment when initGLX() is called. | 242 | // and the GLPlatform has not been initialized at the moment when initGLX() is called. | ||
250 | glXQueryDrawable = nullptr; | 243 | glXQueryDrawable = nullptr; | ||
251 | } | 244 | } | ||
252 | 245 | | |||
253 | setIsDirectRendering(bool(glXIsDirect(display(), ctx))); | 246 | setIsDirectRendering(bool(glXIsDirect(display(), ctx))); | ||
▲ Show 20 Lines • Show All 389 Lines • ▼ Show 20 Line(s) | 631 | if (info->fbconfig) { | |||
643 | glXGetFBConfigAttrib(display(), info->fbconfig, GLX_VISUAL_ID, &visual_id); | 636 | glXGetFBConfigAttrib(display(), info->fbconfig, GLX_VISUAL_ID, &visual_id); | ||
644 | 637 | | |||
645 | qCDebug(KWIN_X11STANDALONE).nospace() << "Using FBConfig 0x" << hex << fbc_id << " for visual 0x" << hex << visual_id; | 638 | qCDebug(KWIN_X11STANDALONE).nospace() << "Using FBConfig 0x" << hex << fbc_id << " for visual 0x" << hex << visual_id; | ||
646 | } | 639 | } | ||
647 | 640 | | |||
648 | return info; | 641 | return info; | ||
649 | } | 642 | } | ||
650 | 643 | | |||
651 | void GlxBackend::setSwapInterval(int interval) | | |||
652 | { | | |||
653 | if (m_haveEXTSwapControl) | | |||
654 | glXSwapIntervalEXT(display(), glxWindow, interval); | | |||
655 | else if (m_haveMESASwapControl) | | |||
656 | glXSwapIntervalMESA(interval); | | |||
657 | } | | |||
658 | | ||||
659 | void GlxBackend::present() | 644 | void GlxBackend::present() | ||
660 | { | 645 | { | ||
661 | if (lastDamage().isEmpty()) | 646 | if (lastDamage().isEmpty()) | ||
662 | return; | 647 | return; | ||
663 | 648 | | |||
664 | const QSize &screenSize = screens()->size(); | 649 | const QSize &screenSize = screens()->size(); | ||
665 | const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height()); | 650 | const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height()); | ||
666 | const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion); | 651 | const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion); | ||
667 | 652 | | |||
668 | if (fullRepaint) { | 653 | if (fullRepaint) { | ||
669 | if (m_haveINTELSwapEvent) | 654 | if (m_haveINTELSwapEvent) | ||
670 | Compositor::self()->aboutToSwapBuffers(); | 655 | Compositor::self()->aboutToSwapBuffers(); | ||
671 | 656 | | |||
672 | if (haveSwapInterval) { | | |||
673 | glXSwapBuffers(display(), glxWindow); | | |||
674 | } else { | | |||
675 | glXSwapBuffers(display(), glxWindow); | 657 | glXSwapBuffers(display(), glxWindow); | ||
676 | } | 658 | | ||
677 | if (supportsBufferAge()) { | 659 | if (supportsBufferAge()) { | ||
678 | glXQueryDrawable(display(), glxWindow, GLX_BACK_BUFFER_AGE_EXT, (GLuint *) &m_bufferAge); | 660 | glXQueryDrawable(display(), glxWindow, GLX_BACK_BUFFER_AGE_EXT, (GLuint *) &m_bufferAge); | ||
679 | } | 661 | } | ||
680 | } else if (m_haveMESACopySubBuffer) { | 662 | } else if (m_haveMESACopySubBuffer) { | ||
681 | for (const QRect &r : lastDamage()) { | 663 | for (const QRect &r : lastDamage()) { | ||
682 | // convert to OpenGL coordinates | 664 | // convert to OpenGL coordinates | ||
683 | int y = screenSize.height() - r.y() - r.height(); | 665 | int y = screenSize.height() - r.y() - r.height(); | ||
684 | glXCopySubBufferMESA(display(), glxWindow, r.x(), y, r.width(), r.height()); | 666 | glXCopySubBufferMESA(display(), glxWindow, r.x(), y, r.width(), r.height()); | ||
▲ Show 20 Lines • Show All 201 Lines • Show Last 20 Lines |