diff options
Diffstat (limited to 'src/frontend/qt_sdl/main.cpp')
-rw-r--r-- | src/frontend/qt_sdl/main.cpp | 595 |
1 files changed, 338 insertions, 257 deletions
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 88704b6..cd0ea52 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -37,17 +37,20 @@ #include <QMimeData> #include <QVector> #ifndef _WIN32 +#include <QGuiApplication> #include <QSocketNotifier> #include <unistd.h> #include <sys/socket.h> #include <signal.h> +#ifndef APPLE +#include <qpa/qplatformnativeinterface.h> +#endif #endif #include <SDL2/SDL.h> -#ifdef OGLRENDERER_ENABLED #include "OpenGLSupport.h" -#endif +#include "duckstation/gl/context.h" #include "main.h" #include "Input.h" @@ -369,51 +372,121 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) connect(this, SIGNAL(windowFullscreenToggle()), mainWindow, SLOT(onFullscreenToggled())); connect(this, SIGNAL(swapScreensToggle()), mainWindow->actScreenSwap, SLOT(trigger())); - if (mainWindow->hasOGL) initOpenGL(); + static_cast<ScreenPanelGL*>(mainWindow->panel)->transferLayout(this); } -void EmuThread::initOpenGL() +void EmuThread::updateScreenSettings(bool filter, const WindowInfo& windowInfo, int numScreens, int* screenKind, float* screenMatrix) { - QOpenGLContext* windowctx = mainWindow->getOGLContext(); - QSurfaceFormat format = windowctx->format(); - - format.setSwapInterval(0); + screenSettingsLock.lock(); - oglSurface = new QOffscreenSurface(); - oglSurface->setFormat(format); - oglSurface->create(); - if (!oglSurface->isValid()) + if (lastScreenWidth != windowInfo.surface_width || lastScreenHeight != windowInfo.surface_height) { - // TODO handle this! - printf("oglSurface shat itself :(\n"); - delete oglSurface; - return; + if (oglContext) + oglContext->ResizeSurface(windowInfo.surface_width, windowInfo.surface_height); + lastScreenWidth = windowInfo.surface_width; + lastScreenHeight = windowInfo.surface_height; } - oglContext = new QOpenGLContext(); - oglContext->setFormat(oglSurface->format()); - oglContext->setShareContext(windowctx); - if (!oglContext->create()) + this->filter = filter; + this->windowInfo = windowInfo; + this->numScreens = numScreens; + memcpy(this->screenKind, screenKind, sizeof(int)*numScreens); + memcpy(this->screenMatrix, screenMatrix, sizeof(float)*numScreens*6); + + screenSettingsLock.unlock(); +} + +void EmuThread::initOpenGL() +{ + GL::Context* windowctx = mainWindow->getOGLContext(); + + oglContext = windowctx; + oglContext->MakeCurrent(); + + OpenGL::BuildShaderProgram(kScreenVS, kScreenFS, screenShaderProgram, "ScreenShader"); + GLuint pid = screenShaderProgram[2]; + glBindAttribLocation(pid, 0, "vPosition"); + glBindAttribLocation(pid, 1, "vTexcoord"); + glBindFragDataLocation(pid, 0, "oColor"); + + OpenGL::LinkShaderProgram(screenShaderProgram); + + glUseProgram(pid); + glUniform1i(glGetUniformLocation(pid, "ScreenTex"), 0); + + screenShaderScreenSizeULoc = glGetUniformLocation(pid, "uScreenSize"); + screenShaderTransformULoc = glGetUniformLocation(pid, "uTransform"); + + // to prevent bleeding between both parts of the screen + // with bilinear filtering enabled + const int paddedHeight = 192*2+2; + const float padPixels = 1.f / paddedHeight; + + const float vertices[] = { - // TODO handle this! - printf("oglContext shat itself :(\n"); - delete oglContext; - delete oglSurface; - return; - } + 0.f, 0.f, 0.f, 0.f, + 0.f, 192.f, 0.f, 0.5f - padPixels, + 256.f, 192.f, 1.f, 0.5f - padPixels, + 0.f, 0.f, 0.f, 0.f, + 256.f, 192.f, 1.f, 0.5f - padPixels, + 256.f, 0.f, 1.f, 0.f, + + 0.f, 0.f, 0.f, 0.5f + padPixels, + 0.f, 192.f, 0.f, 1.f, + 256.f, 192.f, 1.f, 1.f, + 0.f, 0.f, 0.f, 0.5f + padPixels, + 256.f, 192.f, 1.f, 1.f, + 256.f, 0.f, 1.f, 0.5f + padPixels + }; + + glGenBuffers(1, &screenVertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, screenVertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glGenVertexArrays(1, &screenVertexArray); + glBindVertexArray(screenVertexArray); + glEnableVertexAttribArray(0); // position + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(0)); + glEnableVertexAttribArray(1); // texcoord + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(2*4)); + + glGenTextures(1, &screenTexture); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, screenTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, paddedHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + // fill the padding + u8 zeroData[256*4*4]; + memset(zeroData, 0, sizeof(zeroData)); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 2, GL_RGBA, GL_UNSIGNED_BYTE, zeroData); - oglContext->moveToThread(this); + OSD::Init(true); + + oglContext->SetSwapInterval(Config::ScreenVSync ? Config::ScreenVSyncInterval : 0); } void EmuThread::deinitOpenGL() { - delete oglContext; - delete oglSurface; + glDeleteTextures(1, &screenTexture); + + glDeleteVertexArrays(1, &screenVertexArray); + glDeleteBuffers(1, &screenVertexBuffer); + + OpenGL::DeleteShaderProgram(screenShaderProgram); + + OSD::DeInit(); + + oglContext->DoneCurrent(); + oglContext = nullptr; + + lastScreenWidth = lastScreenHeight = -1; } void EmuThread::run() { - bool hasOGL = mainWindow->hasOGL; u32 mainScreenPos[3]; NDS::Init(); @@ -428,14 +501,12 @@ void EmuThread::run() videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor; videoSettings.GL_BetterPolygons = Config::GL_BetterPolygons; -#ifdef OGLRENDERER_ENABLED - if (hasOGL) + if (mainWindow->hasOGL) { - oglContext->makeCurrent(oglSurface); + initOpenGL(); videoRenderer = Config::_3DRenderer; } else -#endif { videoRenderer = 0; } @@ -498,25 +569,24 @@ void EmuThread::run() if (EmuRunning == 3) EmuRunning = 2; // update render settings if needed - if (videoSettingsDirty) + // HACK: + // once the fast forward hotkey is released, we need to update vsync + // to the old setting again + if (videoSettingsDirty || Input::HotkeyReleased(HK_FastForward)) { - if (hasOGL != mainWindow->hasOGL) + if (oglContext) { - hasOGL = mainWindow->hasOGL; -#ifdef OGLRENDERER_ENABLED - if (hasOGL) - { - oglContext->makeCurrent(oglSurface); - videoRenderer = Config::_3DRenderer; - } - else -#endif - { - videoRenderer = 0; - } + oglContext->SetSwapInterval(Config::ScreenVSync ? Config::ScreenVSyncInterval : 0); + videoRenderer = Config::_3DRenderer; } +#ifdef OGLRENDERER_ENABLED else - videoRenderer = hasOGL ? Config::_3DRenderer : 0; +#endif + { + videoRenderer = 0; + } + + videoRenderer = oglContext ? Config::_3DRenderer : 0; videoSettingsDirty = false; @@ -570,15 +640,6 @@ void EmuThread::run() } } -#ifdef OGLRENDERER_ENABLED - if (videoRenderer == 1) - { - FrontBufferLock.lock(); - if (FrontBufferReverseSyncs[FrontBuffer ^ 1]) - glWaitSync(FrontBufferReverseSyncs[FrontBuffer ^ 1], 0, GL_TIMEOUT_IGNORED); - FrontBufferLock.unlock(); - } -#endif // emulate u32 nlines = NDS::RunFrame(); @@ -589,21 +650,17 @@ void EmuThread::run() if (ROMManager::GBASave) ROMManager::GBASave->CheckFlush(); - FrontBufferLock.lock(); - FrontBuffer = GPU::FrontBuffer; -#ifdef OGLRENDERER_ENABLED - if (videoRenderer == 1) + if (!oglContext) { - if (FrontBufferSyncs[FrontBuffer]) - glDeleteSync(FrontBufferSyncs[FrontBuffer]); - FrontBufferSyncs[FrontBuffer] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - // this is hacky but this is the easiest way to call - // this function without dealling with a ton of - // macro mess - epoxy_glFlush(); + FrontBufferLock.lock(); + FrontBuffer = GPU::FrontBuffer; + FrontBufferLock.unlock(); + } + else + { + FrontBuffer = GPU::FrontBuffer; + drawScreenGL(); } -#endif - FrontBufferLock.unlock(); #ifdef MELONCAP MelonCap::Update(); @@ -612,7 +669,7 @@ void EmuThread::run() if (EmuRunning == 0) break; winUpdateCount++; - if (winUpdateCount >= winUpdateFreq) + if (winUpdateCount >= winUpdateFreq && !oglContext) { emit windowUpdate(); winUpdateCount = 0; @@ -620,6 +677,11 @@ void EmuThread::run() bool fastforward = Input::HotkeyDown(HK_FastForward); + if (fastforward && oglContext && Config::ScreenVSync) + { + oglContext->SetSwapInterval(0); + } + if (Config::AudioSync && !fastforward && audioDevice) { SDL_LockMutex(audioSyncLock); @@ -700,6 +762,21 @@ void EmuThread::run() changeWindowTitle(melontitle); SDL_Delay(75); + + if (oglContext) + drawScreenGL(); + + int contextRequest = ContextRequest; + if (contextRequest == 1) + { + initOpenGL(); + ContextRequest = 0; + } + else if (contextRequest == 2) + { + deinitOpenGL(); + ContextRequest = 0; + } } } @@ -708,12 +785,6 @@ void EmuThread::run() GPU::DeInitRenderer(); NDS::DeInit(); //Platform::LAN_DeInit(); - - if (hasOGL) - { - oglContext->doneCurrent(); - deinitOpenGL(); - } } void EmuThread::changeWindowTitle(char* title) @@ -733,6 +804,18 @@ void EmuThread::emuRun() micOpen(); } +void EmuThread::initContext() +{ + ContextRequest = 1; + while (ContextRequest != 0); +} + +void EmuThread::deinitContext() +{ + ContextRequest = 2; + while (ContextRequest != 0); +} + void EmuThread::emuPause() { EmuPause++; @@ -784,6 +867,72 @@ bool EmuThread::emuIsActive() return (RunningSomething == 1); } +void EmuThread::drawScreenGL() +{ + int w = windowInfo.surface_width; + int h = windowInfo.surface_height; + float factor = windowInfo.surface_scale; + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDisable(GL_DEPTH_TEST); + glDepthMask(false); + glDisable(GL_BLEND); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_STENCIL_TEST); + glClear(GL_COLOR_BUFFER_BIT); + + glViewport(0, 0, w, h); + + glUseProgram(screenShaderProgram[2]); + glUniform2f(screenShaderScreenSizeULoc, w / factor, h / factor); + + int frontbuf = FrontBuffer; + glActiveTexture(GL_TEXTURE0); + +#ifdef OGLRENDERER_ENABLED + if (GPU::Renderer != 0) + { + // hardware-accelerated render + GPU::CurGLCompositor->BindOutputTexture(frontbuf); + } + else +#endif + { + // regular render + glBindTexture(GL_TEXTURE_2D, screenTexture); + + if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1]) + { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192+2, 256, 192, GL_RGBA, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); + } + } + + screenSettingsLock.lock(); + + GLint filter = this->filter ? GL_LINEAR : GL_NEAREST; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + + glBindBuffer(GL_ARRAY_BUFFER, screenVertexBuffer); + glBindVertexArray(screenVertexArray); + + for (int i = 0; i < numScreens; i++) + { + glUniformMatrix2x3fv(screenShaderTransformULoc, 1, GL_TRUE, screenMatrix[i]); + glDrawArrays(GL_TRIANGLES, screenKind[i] == 0 ? 0 : 2*3, 2*3); + } + + screenSettingsLock.unlock(); + + OSD::Update(); + OSD::DrawGL(w, h); + + oglContext->SwapBuffers(); +} + ScreenHandler::ScreenHandler(QWidget* widget) { widget->setMouseTracking(true); @@ -1001,12 +1150,12 @@ ScreenPanelNative::ScreenPanelNative(QWidget* parent) : QWidget(parent), ScreenH screenTrans[0].reset(); screenTrans[1].reset(); - OSD::Init(nullptr); + OSD::Init(false); } ScreenPanelNative::~ScreenPanelNative() { - OSD::DeInit(nullptr); + OSD::DeInit(); } void ScreenPanelNative::setupScreenLayout() @@ -1057,7 +1206,7 @@ void ScreenPanelNative::paintEvent(QPaintEvent* event) } } - OSD::Update(nullptr); + OSD::Update(); OSD::DrawNative(painter); } @@ -1105,188 +1254,115 @@ void ScreenPanelNative::onScreenLayoutChanged() } -ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QOpenGLWidget(parent), ScreenHandler(this) -{} - -ScreenPanelGL::~ScreenPanelGL() +ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QWidget(parent), ScreenHandler(this) { - makeCurrent(); - - OSD::DeInit(this); - - glDeleteTextures(1, &screenTexture); + setAutoFillBackground(false); + setAttribute(Qt::WA_NativeWindow, true); + setAttribute(Qt::WA_NoSystemBackground, true); + setAttribute(Qt::WA_PaintOnScreen, true); + setAttribute(Qt::WA_KeyCompression, false); + setFocusPolicy(Qt::StrongFocus); + setMinimumSize(screenGetMinSize()); +} - glDeleteVertexArrays(1, &screenVertexArray); - glDeleteBuffers(1, &screenVertexBuffer); +ScreenPanelGL::~ScreenPanelGL() +{} - delete screenShader; +bool ScreenPanelGL::createContext() +{ + std::optional<WindowInfo> windowInfo = getWindowInfo(); + std::array<GL::Context::Version, 2> versionsToTry = { + GL::Context::Version{GL::Context::Profile::Core, 4, 3}, + GL::Context::Version{GL::Context::Profile::Core, 3, 2}}; + if (windowInfo.has_value()) + { + glContext = GL::Context::Create(*getWindowInfo(), versionsToTry); + glContext->DoneCurrent(); + } - doneCurrent(); + return glContext != nullptr; } -void ScreenPanelGL::setupScreenLayout() +qreal ScreenPanelGL::devicePixelRatioFromScreen() const { - int w = width(); - int h = height(); + const QScreen* screen_for_ratio = window()->windowHandle()->screen(); + if (!screen_for_ratio) + screen_for_ratio = QGuiApplication::primaryScreen(); - screenSetupLayout(w, h); + return screen_for_ratio ? screen_for_ratio->devicePixelRatio() : static_cast<qreal>(1); } -void ScreenPanelGL::initializeGL() +int ScreenPanelGL::scaledWindowWidth() const { - initializeOpenGLFunctions(); - - const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string - const GLubyte* version = glGetString(GL_VERSION); // version as a string - printf("OpenGL: renderer: %s\n", renderer); - printf("OpenGL: version: %s\n", version); - - glClearColor(0, 0, 0, 1); - - screenShader = new QOpenGLShaderProgram(this); - screenShader->addShaderFromSourceCode(QOpenGLShader::Vertex, kScreenVS); - screenShader->addShaderFromSourceCode(QOpenGLShader::Fragment, kScreenFS); - - GLuint pid = screenShader->programId(); - glBindAttribLocation(pid, 0, "vPosition"); - glBindAttribLocation(pid, 1, "vTexcoord"); - glBindFragDataLocation(pid, 0, "oColor"); - - screenShader->link(); + return std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * devicePixelRatioFromScreen())), 1); +} - screenShader->bind(); - screenShader->setUniformValue("ScreenTex", (GLint)0); - screenShader->release(); +int ScreenPanelGL::scaledWindowHeight() const +{ + return std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * devicePixelRatioFromScreen())), 1); +} - // to prevent bleeding between both parts of the screen - // with bilinear filtering enabled - const int paddedHeight = 192*2+2; - const float padPixels = 1.f / paddedHeight; +std::optional<WindowInfo> ScreenPanelGL::getWindowInfo() +{ + WindowInfo wi; - const float vertices[] = + // Windows and Apple are easy here since there's no display connection. + #if defined(_WIN32) + wi.type = WindowInfo::Type::Win32; + wi.window_handle = reinterpret_cast<void*>(winId()); + #elif defined(__APPLE__) + wi.type = WindowInfo::Type::MacOS; + wi.window_handle = reinterpret_cast<void*>(winId()); + #else + QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface(); + const QString platform_name = QGuiApplication::platformName(); + if (platform_name == QStringLiteral("xcb")) { - 0.f, 0.f, 0.f, 0.f, - 0.f, 192.f, 0.f, 0.5f - padPixels, - 256.f, 192.f, 1.f, 0.5f - padPixels, - 0.f, 0.f, 0.f, 0.f, - 256.f, 192.f, 1.f, 0.5f - padPixels, - 256.f, 0.f, 1.f, 0.f, + wi.type = WindowInfo::Type::X11; + wi.display_connection = pni->nativeResourceForWindow("display", windowHandle()); + wi.window_handle = reinterpret_cast<void*>(winId()); + } + else if (platform_name == QStringLiteral("wayland")) + { + wi.type = WindowInfo::Type::Wayland; + wi.display_connection = pni->nativeResourceForWindow("display", windowHandle()); + wi.window_handle = pni->nativeResourceForWindow("surface", windowHandle()); + } + else + { + qCritical() << "Unknown PNI platform " << platform_name; + return std::nullopt; + } + #endif - 0.f, 0.f, 0.f, 0.5f + padPixels, - 0.f, 192.f, 0.f, 1.f, - 256.f, 192.f, 1.f, 1.f, - 0.f, 0.f, 0.f, 0.5f + padPixels, - 256.f, 192.f, 1.f, 1.f, - 256.f, 0.f, 1.f, 0.5f + padPixels - }; + wi.surface_width = static_cast<u32>(scaledWindowWidth()); + wi.surface_height = static_cast<u32>(scaledWindowHeight()); + wi.surface_scale = static_cast<float>(devicePixelRatioFromScreen()); - glGenBuffers(1, &screenVertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, screenVertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + return wi; +} - glGenVertexArrays(1, &screenVertexArray); - glBindVertexArray(screenVertexArray); - glEnableVertexAttribArray(0); // position - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(0)); - glEnableVertexAttribArray(1); // texcoord - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(2*4)); - glGenTextures(1, &screenTexture); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, screenTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, paddedHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - // fill the padding - u8 zeroData[256*4*4]; - memset(zeroData, 0, sizeof(zeroData)); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 2, GL_RGBA, GL_UNSIGNED_BYTE, zeroData); - - OSD::Init(this); +QPaintEngine* ScreenPanelGL::paintEngine() const +{ + return nullptr; } -void ScreenPanelGL::paintGL() +void ScreenPanelGL::setupScreenLayout() { int w = width(); int h = height(); - float factor = devicePixelRatioF(); - - glClear(GL_COLOR_BUFFER_BIT); - - glViewport(0, 0, w*factor, h*factor); + screenSetupLayout(w, h); if (emuThread) - { - screenShader->bind(); - - screenShader->setUniformValue("uScreenSize", (float)w, (float)h); - screenShader->setUniformValue("uScaleFactor", factor); - - emuThread->FrontBufferLock.lock(); - int frontbuf = emuThread->FrontBuffer; - glActiveTexture(GL_TEXTURE0); - - #ifdef OGLRENDERER_ENABLED - if (GPU::Renderer != 0) - { - if (emuThread->FrontBufferSyncs[emuThread->FrontBuffer]) - glWaitSync(emuThread->FrontBufferSyncs[emuThread->FrontBuffer], 0, GL_TIMEOUT_IGNORED); - // hardware-accelerated render - GPU::CurGLCompositor->BindOutputTexture(frontbuf); - } - else - #endif - { - // regular render - glBindTexture(GL_TEXTURE_2D, screenTexture); - - if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1]) - { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA, - GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192+2, 256, 192, GL_RGBA, - GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); - } - } - - GLint filter = Config::ScreenFilter ? GL_LINEAR : GL_NEAREST; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - - glBindBuffer(GL_ARRAY_BUFFER, screenVertexBuffer); - glBindVertexArray(screenVertexArray); - - GLint transloc = screenShader->uniformLocation("uTransform"); - - for (int i = 0; i < numScreens; i++) - { - glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[i]); - glDrawArrays(GL_TRIANGLES, screenKind[i] == 0 ? 0 : 2*3, 2*3); - } - - screenShader->release(); - - if (emuThread->FrontBufferReverseSyncs[emuThread->FrontBuffer]) - glDeleteSync(emuThread->FrontBufferReverseSyncs[emuThread->FrontBuffer]); - emuThread->FrontBufferReverseSyncs[emuThread->FrontBuffer] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - emuThread->FrontBufferLock.unlock(); - } - - OSD::Update(this); - OSD::DrawGL(this, w*factor, h*factor); + transferLayout(emuThread); } void ScreenPanelGL::resizeEvent(QResizeEvent* event) { setupScreenLayout(); - QOpenGLWidget::resizeEvent(event); -} - -void ScreenPanelGL::resizeGL(int w, int h) -{ + QWidget::resizeEvent(event); } void ScreenPanelGL::mousePressEvent(QMouseEvent* event) @@ -1321,6 +1397,13 @@ bool ScreenPanelGL::event(QEvent* event) return QWidget::event(event); } +void ScreenPanelGL::transferLayout(EmuThread* thread) +{ + std::optional<WindowInfo> windowInfo = getWindowInfo(); + if (windowInfo.has_value()) + thread->updateScreenSettings(Config::ScreenFilter, *windowInfo, numScreens, screenKind, &screenMatrix[0][0]); +} + void ScreenPanelGL::onScreenLayoutChanged() { setMinimumSize(screenGetMinSize()); @@ -1817,6 +1900,18 @@ MainWindow::~MainWindow() { } +void MainWindow::closeEvent(QCloseEvent* event) +{ + if (hasOGL) + { + // we intentionally don't unpause here + emuThread->emuPause(); + emuThread->deinitContext(); + } + + QMainWindow::closeEvent(event); +} + void MainWindow::createScreenPanel() { hasOGL = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); @@ -1829,17 +1924,7 @@ void MainWindow::createScreenPanel() panel = panelGL; panelWidget = panelGL; - if (!panelGL->isValid()) - hasOGL = false; - else - { - QSurfaceFormat fmt = panelGL->format(); - if (fmt.majorVersion() < 3 || (fmt.majorVersion() == 3 && fmt.minorVersion() < 2)) - hasOGL = false; - } - - if (!hasOGL) - delete panelGL; + panelGL->createContext(); } if (!hasOGL) @@ -1855,12 +1940,12 @@ void MainWindow::createScreenPanel() emit screenLayoutChange(); } -QOpenGLContext* MainWindow::getOGLContext() +GL::Context* MainWindow::getOGLContext() { if (!hasOGL) return nullptr; - QOpenGLWidget* glpanel = dynamic_cast<QOpenGLWidget*>(panel); - return glpanel->context(); + ScreenPanelGL* glpanel = static_cast<ScreenPanelGL*>(panel); + return glpanel->getContext(); } void MainWindow::resizeEvent(QResizeEvent* event) @@ -3002,13 +3087,14 @@ void MainWindow::onChangeIntegerScaling(bool checked) void MainWindow::onChangeScreenFiltering(bool checked) { Config::ScreenFilter = checked?1:0; + + emit screenLayoutChange(); } void MainWindow::onChangeShowOSD(bool checked) { Config::ShowOSD = checked?1:0; } - void MainWindow::onChangeLimitFramerate(bool checked) { Config::LimitFPS = checked?1:0; @@ -3088,19 +3174,20 @@ void MainWindow::onUpdateVideoSettings(bool glchange) if (glchange) { emuThread->emuPause(); + if (hasOGL) emuThread->deinitContext(); - if (hasOGL) - emuThread->deinitOpenGL(); delete panel; createScreenPanel(); connect(emuThread, SIGNAL(windowUpdate()), panelWidget, SLOT(repaint())); - if (hasOGL) emuThread->initOpenGL(); } videoSettingsDirty = true; if (glchange) + { + if (hasOGL) emuThread->initContext(); emuThread->emuUnpause(); + } } @@ -3137,6 +3224,8 @@ int main(int argc, char** argv) { srand(time(nullptr)); + qputenv("QT_SCALE_FACTOR", "1"); + printf("melonDS " MELONDS_VERSION "\n"); printf(MELONDS_URL "\n"); @@ -3191,14 +3280,6 @@ int main(int argc, char** argv) SANITIZE(Config::ScreenAspectBot, 0, 4); #undef SANITIZE - QSurfaceFormat format; - format.setDepthBufferSize(24); - format.setStencilBufferSize(8); - format.setVersion(3, 2); - format.setProfile(QSurfaceFormat::CoreProfile); - format.setSwapInterval(0); - QSurfaceFormat::setDefaultFormat(format); - audioMuted = false; audioSync = SDL_CreateCond(); audioSyncLock = SDL_CreateMutex(); |