Changeset View
Changeset View
Standalone View
Standalone View
plugins/platforms/x11/standalone/glxbackend.cpp
Show First 20 Lines • Show All 120 Lines • ▼ Show 20 Line(s) | 117 | { | |||
---|---|---|---|---|---|
121 | setenv("__GL_MaxFramesAllowed", "1", true); | 121 | setenv("__GL_MaxFramesAllowed", "1", true); | ||
122 | 122 | | |||
123 | // Force initialization of GLX integration in the Qt's xcb backend | 123 | // Force initialization of GLX integration in the Qt's xcb backend | ||
124 | // to make it call XESetWireToEvent callbacks, which is required | 124 | // to make it call XESetWireToEvent callbacks, which is required | ||
125 | // by Mesa when using DRI2. | 125 | // by Mesa when using DRI2. | ||
126 | QOpenGLContext::supportsThreadedOpenGL(); | 126 | QOpenGLContext::supportsThreadedOpenGL(); | ||
127 | } | 127 | } | ||
128 | 128 | | |||
129 | static bool gs_tripleBufferUndetected = true; | | |||
130 | static bool gs_tripleBufferNeedsDetection = false; | | |||
131 | | ||||
132 | GlxBackend::~GlxBackend() | 129 | GlxBackend::~GlxBackend() | ||
133 | { | 130 | { | ||
134 | if (isFailed()) { | 131 | if (isFailed()) { | ||
135 | m_overlayWindow->destroy(); | 132 | m_overlayWindow->destroy(); | ||
136 | } | 133 | } | ||
137 | // TODO: cleanup in error case | 134 | // TODO: cleanup in error case | ||
138 | // do cleanup after initBuffer() | 135 | // do cleanup after initBuffer() | ||
139 | cleanupGL(); | 136 | cleanupGL(); | ||
140 | doneCurrent(); | 137 | doneCurrent(); | ||
141 | 138 | | |||
142 | gs_tripleBufferUndetected = true; | | |||
143 | gs_tripleBufferNeedsDetection = false; | | |||
144 | | ||||
145 | if (ctx) | 139 | if (ctx) | ||
146 | glXDestroyContext(display(), ctx); | 140 | glXDestroyContext(display(), ctx); | ||
147 | 141 | | |||
148 | if (glxWindow) | 142 | if (glxWindow) | ||
149 | glXDestroyWindow(display(), glxWindow); | 143 | glXDestroyWindow(display(), glxWindow); | ||
150 | 144 | | |||
151 | if (window) | 145 | if (window) | ||
152 | XDestroyWindow(display(), window); | 146 | XDestroyWindow(display(), window); | ||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Line(s) | 227 | if (hasExtension(QByteArrayLiteral("GLX_EXT_buffer_age"))) { | |||
235 | 229 | | |||
236 | if (useBufferAge != "0") | 230 | if (useBufferAge != "0") | ||
237 | setSupportsBufferAge(true); | 231 | setSupportsBufferAge(true); | ||
238 | } | 232 | } | ||
239 | 233 | | |||
240 | setSyncsToVBlank(false); | 234 | setSyncsToVBlank(false); | ||
241 | setBlocksForRetrace(false); | 235 | setBlocksForRetrace(false); | ||
242 | haveWaitSync = false; | 236 | haveWaitSync = false; | ||
243 | gs_tripleBufferNeedsDetection = false; | | |||
244 | m_swapProfiler.init(); | | |||
245 | const bool wantSync = options->glPreferBufferSwap() != Options::NoSwapEncourage; | 237 | const bool wantSync = options->glPreferBufferSwap() != Options::NoSwapEncourage; | ||
246 | if (wantSync && glXIsDirect(display(), ctx)) { | 238 | if (wantSync && glXIsDirect(display(), ctx)) { | ||
247 | if (haveSwapInterval) { // glXSwapInterval is preferred being more reliable | 239 | if (haveSwapInterval) { // glXSwapInterval is preferred being more reliable | ||
248 | setSwapInterval(1); | 240 | setSwapInterval(1); | ||
249 | setSyncsToVBlank(true); | 241 | setSyncsToVBlank(true); | ||
250 | const QByteArray tripleBuffer = qgetenv("KWIN_TRIPLE_BUFFER"); | | |||
251 | if (!tripleBuffer.isEmpty()) { | | |||
252 | setBlocksForRetrace(qstrcmp(tripleBuffer, "0") == 0); | | |||
253 | gs_tripleBufferUndetected = false; | | |||
254 | } | | |||
255 | gs_tripleBufferNeedsDetection = gs_tripleBufferUndetected; | | |||
256 | } else if (hasExtension(QByteArrayLiteral("GLX_SGI_video_sync"))) { | 242 | } else if (hasExtension(QByteArrayLiteral("GLX_SGI_video_sync"))) { | ||
257 | unsigned int sync; | 243 | unsigned int sync; | ||
258 | if (glXGetVideoSyncSGI(&sync) == 0 && glXWaitVideoSyncSGI(1, 0, &sync) == 0) { | 244 | if (glXGetVideoSyncSGI(&sync) == 0 && glXWaitVideoSyncSGI(1, 0, &sync) == 0) { | ||
259 | setSyncsToVBlank(true); | 245 | setSyncsToVBlank(true); | ||
260 | setBlocksForRetrace(true); | 246 | setBlocksForRetrace(true); | ||
261 | haveWaitSync = true; | 247 | haveWaitSync = true; | ||
262 | } else | 248 | } else | ||
263 | qCWarning(KWIN_X11STANDALONE) << "NO VSYNC! glXSwapInterval is not supported, glXWaitVideoSync is supported but broken"; | 249 | qCWarning(KWIN_X11STANDALONE) << "NO VSYNC! glXSwapInterval is not supported, glXWaitVideoSync is supported but broken"; | ||
▲ Show 20 Lines • Show All 444 Lines • ▼ Show 20 Line(s) | 689 | { | |||
708 | const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height()); | 694 | const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height()); | ||
709 | const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion); | 695 | const bool fullRepaint = supportsBufferAge() || (lastDamage() == displayRegion); | ||
710 | 696 | | |||
711 | if (fullRepaint) { | 697 | if (fullRepaint) { | ||
712 | if (m_haveINTELSwapEvent) | 698 | if (m_haveINTELSwapEvent) | ||
713 | Compositor::self()->aboutToSwapBuffers(); | 699 | Compositor::self()->aboutToSwapBuffers(); | ||
714 | 700 | | |||
715 | if (haveSwapInterval) { | 701 | if (haveSwapInterval) { | ||
716 | if (gs_tripleBufferNeedsDetection) { | | |||
717 | glXWaitGL(); | | |||
718 | m_swapProfiler.begin(); | | |||
719 | } | | |||
720 | glXSwapBuffers(display(), glxWindow); | 702 | glXSwapBuffers(display(), glxWindow); | ||
721 | if (gs_tripleBufferNeedsDetection) { | | |||
722 | glXWaitGL(); | | |||
723 | if (char result = m_swapProfiler.end()) { | | |||
724 | gs_tripleBufferUndetected = gs_tripleBufferNeedsDetection = false; | | |||
725 | setBlocksForRetrace(result == 'd'); | | |||
726 | } | | |||
727 | } | | |||
728 | } else { | 703 | } else { | ||
729 | waitSync(); | 704 | waitSync(); | ||
730 | glXSwapBuffers(display(), glxWindow); | 705 | glXSwapBuffers(display(), glxWindow); | ||
731 | } | 706 | } | ||
732 | if (supportsBufferAge()) { | 707 | if (supportsBufferAge()) { | ||
733 | glXQueryDrawable(display(), glxWindow, GLX_BACK_BUFFER_AGE_EXT, (GLuint *) &m_bufferAge); | 708 | glXQueryDrawable(display(), glxWindow, GLX_BACK_BUFFER_AGE_EXT, (GLuint *) &m_bufferAge); | ||
734 | } | 709 | } | ||
735 | } else if (m_haveMESACopySubBuffer) { | 710 | } else if (m_haveMESACopySubBuffer) { | ||
Show All 34 Lines | |||||
770 | { | 745 | { | ||
771 | return new GlxTexture(texture, this); | 746 | return new GlxTexture(texture, this); | ||
772 | } | 747 | } | ||
773 | 748 | | |||
774 | QRegion GlxBackend::prepareRenderingFrame() | 749 | QRegion GlxBackend::prepareRenderingFrame() | ||
775 | { | 750 | { | ||
776 | QRegion repaint; | 751 | QRegion repaint; | ||
777 | 752 | | |||
778 | if (gs_tripleBufferNeedsDetection) { | | |||
779 | // the composite timer floors the repaint frequency. This can pollute our triple buffering | | |||
780 | // detection because the glXSwapBuffers call for the new frame has to wait until the pending | | |||
781 | // one scanned out. | | |||
782 | // So we compensate for that by waiting an extra milisecond to give the driver the chance to | | |||
783 | // fllush the buffer queue | | |||
784 | usleep(1000); | | |||
785 | } | | |||
786 | | ||||
787 | present(); | 753 | present(); | ||
788 | 754 | | |||
789 | if (supportsBufferAge()) | 755 | if (supportsBufferAge()) | ||
790 | repaint = accumulatedDamageHistory(m_bufferAge); | 756 | repaint = accumulatedDamageHistory(m_bufferAge); | ||
791 | 757 | | |||
792 | startRenderTimer(); | 758 | startRenderTimer(); | ||
793 | glXWaitX(); | 759 | glXWaitX(); | ||
794 | 760 | | |||
▲ Show 20 Lines • Show All 155 Lines • Show Last 20 Lines |