void CWinSystemX11GL::SetVSyncImpl(bool enable) { /* turn of current setting first */ if(m_glXSwapIntervalSGI) m_glXSwapIntervalSGI(0); if(m_glXSwapIntervalMESA) m_glXSwapIntervalMESA(0); m_iVSyncErrors = 0; CStdString strVendor(m_RenderVendor); strVendor.ToLower(); if(!enable) return; bool vendor_nvidia = strVendor.find("nvidia") != std::string::npos; bool vendor_ati = strVendor.compare(0, 3, "ati") == 0; if (m_glXSwapIntervalMESA && !m_iVSyncMode && vendor_ati) { if(m_glXSwapIntervalMESA(1) == 0) m_iVSyncMode = 2; else CLog::Log(LOGWARNING, "%s - glXSwapIntervalMESA failed", __FUNCTION__); } if(m_glXGetSyncValuesOML && m_glXSwapBuffersMscOML && !m_iVSyncMode) { int64_t ust, msc, sbc; if(m_glXGetSyncValuesOML(m_dpy, m_glWindow, &ust, &msc, &sbc)) m_iVSyncMode = 5; else CLog::Log(LOGWARNING, "%s - glXGetSyncValuesOML failed", __FUNCTION__); } if (m_glXWaitVideoSyncSGI && m_glXGetVideoSyncSGI && !m_iVSyncMode && !vendor_nvidia) { unsigned int count; if(m_glXGetVideoSyncSGI(&count) == 0) m_iVSyncMode = 3; else CLog::Log(LOGWARNING, "%s - glXGetVideoSyncSGI failed, glcontext probably not direct", __FUNCTION__); } if (m_glXSwapIntervalSGI && !m_iVSyncMode) { if(m_glXSwapIntervalSGI(1) == 0) m_iVSyncMode = 2; else CLog::Log(LOGWARNING, "%s - glXSwapIntervalSGI failed", __FUNCTION__); } if (m_glXSwapIntervalMESA && !m_iVSyncMode && !vendor_ati) { if(m_glXSwapIntervalMESA(1) == 0) m_iVSyncMode = 2; else CLog::Log(LOGWARNING, "%s - glXSwapIntervalMESA failed", __FUNCTION__); } }
bool CWinSystemX11GL::PresentRenderImpl(const CDirtyRegionList& dirty) { CheckDisplayEvents(); if(m_iVSyncMode == 3) { glFinish(); unsigned int before = 0, after = 0; if(m_glXGetVideoSyncSGI(&before) != 0) CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__); glXSwapBuffers(m_dpy, m_glWindow); glFinish(); if(m_glXGetVideoSyncSGI(&after) != 0) CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__); if(after == before) m_iVSyncErrors = 1; else m_iVSyncErrors--; if(m_iVSyncErrors > 0) { CLog::Log(LOGINFO, "GL: retrace count didn't change after buffer swap, switching to vsync mode 4"); m_iVSyncErrors = 0; m_iVSyncMode = 4; } if(m_iVSyncErrors < -200) { CLog::Log(LOGINFO, "GL: retrace count change for %d consecutive buffer swap, switching to vsync mode 2", -m_iVSyncErrors); m_iVSyncErrors = 0; m_iVSyncMode = 2; } } else if (m_iVSyncMode == 4) { glFinish(); unsigned int before = 0, swap = 0, after = 0; if(m_glXGetVideoSyncSGI(&before) != 0) CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__); if(m_glXWaitVideoSyncSGI(2, (before+1)%2, &swap) != 0) CLog::Log(LOGERROR, "%s - glXWaitVideoSyncSGI - Returned error", __FUNCTION__); glXSwapBuffers(m_dpy, m_glWindow); glFinish(); if(m_glXGetVideoSyncSGI(&after) != 0) CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__); if(after == before) CLog::Log(LOGERROR, "%s - glXWaitVideoSyncSGI - Woke up early", __FUNCTION__); if(after > before + 1) m_iVSyncErrors++; else m_iVSyncErrors = 0; if(m_iVSyncErrors > 30) { CLog::Log(LOGINFO, "GL: retrace count seems to be changing due to the swapbuffers call, switching to vsync mode 3"); m_iVSyncMode = 3; m_iVSyncErrors = 0; } } else if (m_iVSyncMode == 5) { int64_t ust, msc, sbc; if(m_glXGetSyncValuesOML(m_dpy, m_glWindow, &ust, &msc, &sbc)) m_glXSwapBuffersMscOML(m_dpy, m_glWindow, msc, 0, 0); else CLog::Log(LOGERROR, "%s - glXSwapBuffersMscOML - Failed to get current retrace count", __FUNCTION__); } else glXSwapBuffers(m_dpy, m_glWindow); return true; }