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