qt: Partially fix Wayland support. (#7054)

* qt: Partially fix Wayland on NVIDIA.

* qt: Fix Vulkan under Wayland.

Showing and hiding the window here messes up the surface,
causing an instant crash on load.

* qt: Properly set up GLES context when requested.
This commit is contained in:
Steveice10 2023-10-09 14:58:38 -07:00 committed by GitHub
parent 6244f9e3fd
commit 6cfd00e42d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 11 deletions

View file

@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <glad/glad.h>
#include <QApplication> #include <QApplication>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QKeyEvent> #include <QKeyEvent>
@ -29,6 +27,8 @@
#include "video_core/video_core.h" #include "video_core/video_core.h"
#ifdef HAS_OPENGL #ifdef HAS_OPENGL
#include <glad/glad.h>
#include <QOffscreenSurface> #include <QOffscreenSurface>
#include <QOpenGLContext> #include <QOpenGLContext>
#endif #endif
@ -144,7 +144,13 @@ public:
explicit OpenGLSharedContext() { explicit OpenGLSharedContext() {
QSurfaceFormat format; QSurfaceFormat format;
format.setVersion(4, 3); if (Settings::values.use_gles) {
format.setRenderableType(QSurfaceFormat::RenderableType::OpenGLES);
format.setVersion(3, 2);
} else {
format.setRenderableType(QSurfaceFormat::RenderableType::OpenGL);
format.setVersion(4, 3);
}
format.setProfile(QSurfaceFormat::CoreProfile); format.setProfile(QSurfaceFormat::CoreProfile);
if (Settings::values.renderer_debug) { if (Settings::values.renderer_debug) {
@ -364,7 +370,8 @@ static Frontend::WindowSystemType GetWindowSystemType() {
return Frontend::WindowSystemType::Windows; return Frontend::WindowSystemType::Windows;
else if (platform_name == QStringLiteral("xcb")) else if (platform_name == QStringLiteral("xcb"))
return Frontend::WindowSystemType::X11; return Frontend::WindowSystemType::X11;
else if (platform_name == QStringLiteral("wayland")) else if (platform_name == QStringLiteral("wayland") ||
platform_name == QStringLiteral("wayland-egl"))
return Frontend::WindowSystemType::Wayland; return Frontend::WindowSystemType::Wayland;
else if (platform_name == QStringLiteral("cocoa") || platform_name == QStringLiteral("ios")) else if (platform_name == QStringLiteral("cocoa") || platform_name == QStringLiteral("ios"))
return Frontend::WindowSystemType::MacOS; return Frontend::WindowSystemType::MacOS;
@ -413,7 +420,8 @@ GRenderWindow::GRenderWindow(QWidget* parent_, EmuThread* emu_thread_, Core::Sys
setLayout(layout); setLayout(layout);
this->setMouseTracking(true); this->setMouseTracking(true);
strict_context_required = QGuiApplication::platformName() == QStringLiteral("wayland"); strict_context_required = QGuiApplication::platformName() == QStringLiteral("wayland") ||
QGuiApplication::platformName() == QStringLiteral("wayland-egl");
GMainWindow* parent = GetMainWindow(); GMainWindow* parent = GetMainWindow();
connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete); connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete);
@ -721,10 +729,19 @@ void GRenderWindow::InitializeSoftware() {
main_context = std::make_unique<DummyContext>(); main_context = std::make_unique<DummyContext>();
} }
#ifdef HAS_OPENGL
static void* GetProcAddressGL(const char* name) {
return reinterpret_cast<void*>(QOpenGLContext::currentContext()->getProcAddress(name));
}
#endif
bool GRenderWindow::LoadOpenGL() { bool GRenderWindow::LoadOpenGL() {
#ifdef HAS_OPENGL
auto context = CreateSharedContext(); auto context = CreateSharedContext();
auto scope = context->Acquire(); auto scope = context->Acquire();
if (!gladLoadGL()) {
auto gl_load_func = Settings::values.use_gles ? gladLoadGLES2Loader : gladLoadGLLoader;
if (!gl_load_func(GetProcAddressGL)) {
QMessageBox::warning( QMessageBox::warning(
this, tr("Error while initializing OpenGL!"), this, tr("Error while initializing OpenGL!"),
tr("Your GPU may not support OpenGL, or you do not have the latest graphics driver.")); tr("Your GPU may not support OpenGL, or you do not have the latest graphics driver."));
@ -734,16 +751,28 @@ bool GRenderWindow::LoadOpenGL() {
const QString renderer = const QString renderer =
QString::fromUtf8(reinterpret_cast<const char*>(glGetString(GL_RENDERER))); QString::fromUtf8(reinterpret_cast<const char*>(glGetString(GL_RENDERER)));
if (!GLAD_GL_VERSION_4_3) { if (!Settings::values.use_gles && !GLAD_GL_VERSION_4_3) {
LOG_ERROR(Frontend, "GPU does not support OpenGL 4.3: {}", renderer.toStdString()); LOG_ERROR(Frontend, "GPU does not support OpenGL 4.3: {}", renderer.toStdString());
QMessageBox::warning(this, tr("Error while initializing OpenGL 4.3!"), QMessageBox::warning(this, tr("Error while initializing OpenGL 4.3!"),
tr("Your GPU may not support OpenGL 4.3, or you do not have the " tr("Your GPU may not support OpenGL 4.3, or you do not have the "
"latest graphics driver.<br><br>GL Renderer:<br>%1") "latest graphics driver.<br><br>GL Renderer:<br>%1")
.arg(renderer)); .arg(renderer));
return false; return false;
} else if (Settings::values.use_gles && !GLAD_GL_ES_VERSION_3_2) {
LOG_ERROR(Frontend, "GPU does not support OpenGL ES 3.2: {}", renderer.toStdString());
QMessageBox::warning(this, tr("Error while initializing OpenGL ES 3.2!"),
tr("Your GPU may not support OpenGL ES 3.2, or you do not have the "
"latest graphics driver.<br><br>GL Renderer:<br>%1")
.arg(renderer));
return false;
} }
return true; return true;
#else
QMessageBox::warning(this, tr("OpenGL not available!"),
tr("Citra has not been compiled with OpenGL support."));
return false;
#endif
} }
void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread) { void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread) {

View file

@ -1270,10 +1270,6 @@ void GMainWindow::BootGame(const QString& filename) {
setMouseTracking(true); setMouseTracking(true);
} }
// show and hide the render_window to create the context
render_window->show();
render_window->hide();
loading_screen->Prepare(system.GetAppLoader()); loading_screen->Prepare(system.GetAppLoader());
loading_screen->show(); loading_screen->show();