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