From 70bbe06bfb1ad4fc323abb1259fa773609630ade Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 18 Apr 2023 17:47:33 -0700 Subject: [PATCH] Qt: Manually toggle swap interval as needed --- CMakeLists.txt | 7 +++++ src/platform/qt/Display.cpp | 1 + src/platform/qt/Display.h | 1 + src/platform/qt/DisplayGL.cpp | 48 +++++++++++++++++++++++++++++++++++ src/platform/qt/DisplayGL.h | 3 +++ src/platform/qt/DisplayQt.h | 1 + src/platform/qt/Window.cpp | 9 ++++++- 7 files changed, 69 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a00e93371..deb77146d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -419,6 +419,13 @@ if(BUILD_GL) elseif(UNIX AND NOT APPLE AND TARGET OpenGL::GL) set(OPENGL_LIBRARY OpenGL::GL) endif() + if(OpenGL_GLX_FOUND) + list(APPEND FEATURES GLX) + endif() + if(OpenGL_EGL_FOUND) + list(APPEND FEATURES EGL) + list(APPEND OPENGL_LIBRARY ${OPENGL_egl_LIBRARY}) + endif() endif() if(BUILD_GL) list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gl.c) diff --git a/src/platform/qt/Display.cpp b/src/platform/qt/Display.cpp index 0d1e7672d..95d046f5d 100644 --- a/src/platform/qt/Display.cpp +++ b/src/platform/qt/Display.cpp @@ -111,6 +111,7 @@ void QGBA::Display::configure(ConfigController* config) { filter(opts->resampleVideo); config->updateOption("showOSD"); config->updateOption("showFrameCounter"); + config->updateOption("videoSync"); #if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) if (opts->shader && supportsShaders()) { struct VDir* shader = VDirOpen(opts->shader); diff --git a/src/platform/qt/Display.h b/src/platform/qt/Display.h index af3cf7f00..2c16dd4e9 100644 --- a/src/platform/qt/Display.h +++ b/src/platform/qt/Display.h @@ -72,6 +72,7 @@ public slots: virtual void showOSDMessages(bool enable); virtual void showFrameCounter(bool enable); virtual void filter(bool filter); + virtual void swapInterval(int interval) = 0; virtual void framePosted() = 0; virtual void setShaders(struct VDir*) = 0; virtual void clearShaders() = 0; diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 9d93a6b57..3ac10042b 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -38,6 +38,21 @@ using QOpenGLFunctions_Baseline = QOpenGLFunctions_3_2_Core; #endif #endif +#ifdef _WIN32 +#include +#elif defined(Q_OS_MAC) +#include +#endif +#ifdef USE_GLX +#define GLX_GLXEXT_PROTOTYPES +typedef struct _XDisplay Display; +#include +#include +#endif +#ifdef USE_EGL +#include +#endif + #ifdef _WIN32 #define OVERHEAD_NSEC 1000000 #else @@ -412,6 +427,10 @@ void DisplayGL::filter(bool filter) { QMetaObject::invokeMethod(m_painter.get(), "filter", Q_ARG(bool, filter)); } +void DisplayGL::swapInterval(int interval) { + QMetaObject::invokeMethod(m_painter.get(), "swapInterval", Q_ARG(int, interval)); +} + void DisplayGL::framePosted() { m_painter->enqueue(m_context->drawContext()); QMetaObject::invokeMethod(m_painter.get(), "draw"); @@ -717,6 +736,32 @@ void PainterGL::filter(bool filter) { } } +void PainterGL::swapInterval(int interval) { + if (!m_started) { + return; + } + m_swapInterval = interval; +#ifdef Q_OS_WIN + wglSwapIntervalEXT(interval); +#elif defined(Q_OS_MAC) + CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &interval); +#else +#ifdef USE_GLX + if (QGuiApplication::platformName() == "xcb") { + ::Display* display = glXGetCurrentDisplay(); + GLXDrawable drawable = glXGetCurrentDrawable(); + glXSwapIntervalEXT(display, drawable, interval); + } +#endif +#ifdef USE_EGL + if (QGuiApplication::platformName().contains("egl")) { + EGLDisplay display = eglGetCurrentDisplay(); + eglSwapInterval(display, interval); + } +#endif +#endif +} + #ifndef GL_DEBUG_OUTPUT_SYNCHRONOUS #define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 #endif @@ -773,6 +818,9 @@ void PainterGL::draw() { } return; } + if (m_swapInterval != !!sync->videoFrameWait) { + swapInterval(!!sync->videoFrameWait); + } dequeue(); bool forceRedraw = true; if (!m_delayTimer.isValid()) { diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index 129d8adc4..b5b9b9ebd 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -108,6 +108,7 @@ public slots: void showOSDMessages(bool enable) override; void showFrameCounter(bool enable) override; void filter(bool filter) override; + void swapInterval(int interval) override; void framePosted() override; void setShaders(struct VDir*) override; void clearShaders() override; @@ -182,6 +183,7 @@ public slots: void showOSD(bool enable); void showFrameCounter(bool enable); void filter(bool filter); + void swapInterval(int interval); void resizeContext(); void updateFramebufferHandle(); @@ -240,6 +242,7 @@ private: MessagePainter* m_messagePainter = nullptr; QElapsedTimer m_delayTimer; std::shared_ptr m_videoProxy; + int m_swapInterval = -1; }; } diff --git a/src/platform/qt/DisplayQt.h b/src/platform/qt/DisplayQt.h index e8623468f..0b2fddbc0 100644 --- a/src/platform/qt/DisplayQt.h +++ b/src/platform/qt/DisplayQt.h @@ -31,6 +31,7 @@ public slots: void lockAspectRatio(bool lock) override; void lockIntegerScaling(bool lock) override; void interframeBlending(bool enable) override; + void swapInterval(int) override {}; void filter(bool filter) override; void framePosted() override; void setShaders(struct VDir*) override {} diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 0aee02e9d..b63e846e8 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1788,7 +1788,14 @@ void Window::setupMenu(QMenuBar* menubar) { void Window::setupOptions() { ConfigOption* videoSync = m_config->addOption("videoSync"); - videoSync->connect([this](const QVariant&) { + videoSync->connect([this](const QVariant& variant) { + if (m_display) { + bool ok; + int interval = variant.toInt(&ok); + if (ok) { + m_display->swapInterval(interval); + } + } reloadConfig(); }, this);