From 7337edb82a5a574ac9ad77a27a9ad571889f8d51 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 af45bd9b6..c80e2350e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -422,6 +422,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 fcbec86bc..f8b803558 100644 --- a/src/platform/qt/Display.cpp +++ b/src/platform/qt/Display.cpp @@ -112,6 +112,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 4fc100799..6830e8515 100644 --- a/src/platform/qt/Display.h +++ b/src/platform/qt/Display.h @@ -76,6 +76,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 1913dc27c..f04629d8a 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 @@ -416,6 +431,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"); @@ -755,6 +774,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 @@ -811,6 +856,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 759789609..0190eb30a 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -109,6 +109,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; @@ -186,6 +187,7 @@ public slots: void showOSD(bool enable); void showFrameCounter(bool enable); void filter(bool filter); + void swapInterval(int interval); void resizeContext(); void updateFramebufferHandle(); void setBackgroundImage(const QImage&); @@ -248,6 +250,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 8ea6cc80a..78deb2042 100644 --- a/src/platform/qt/DisplayQt.h +++ b/src/platform/qt/DisplayQt.h @@ -32,6 +32,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 bb97bf5c3..4da4c33ab 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1759,7 +1759,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);