Просмотр исходного кода

Merge pull request #7410 from Nefsen402/wayland-fixes

Wayland fixes
liamwhite 3 лет назад
Родитель
Сommit
3ff7a5de1a

+ 6 - 0
src/core/frontend/emu_window.h

@@ -131,6 +131,10 @@ public:
         return active_config;
         return active_config;
     }
     }
 
 
+    bool StrictContextRequired() const {
+        return strict_context_required;
+    }
+
     /**
     /**
      * Requests the internal configuration to be replaced by the specified argument at some point in
      * Requests the internal configuration to be replaced by the specified argument at some point in
      * the future.
      * the future.
@@ -207,6 +211,8 @@ protected:
 
 
     WindowSystemInfo window_info;
     WindowSystemInfo window_info;
 
 
+    bool strict_context_required = false;
+
 private:
 private:
     /**
     /**
      * Handler called when the minimal client area was requested to be changed via SetConfig.
      * Handler called when the minimal client area was requested to be changed via SetConfig.

+ 3 - 2
src/video_core/gpu.cpp

@@ -223,8 +223,6 @@ struct GPU::Impl {
     /// core timing events.
     /// core timing events.
     void Start() {
     void Start() {
         gpu_thread.StartThread(*renderer, renderer->Context(), *scheduler);
         gpu_thread.StartThread(*renderer, renderer->Context(), *scheduler);
-        cpu_context = renderer->GetRenderWindow().CreateSharedContext();
-        cpu_context->MakeCurrent();
     }
     }
 
 
     void NotifyShutdown() {
     void NotifyShutdown() {
@@ -235,6 +233,9 @@ struct GPU::Impl {
 
 
     /// Obtain the CPU Context
     /// Obtain the CPU Context
     void ObtainContext() {
     void ObtainContext() {
+        if (!cpu_context) {
+            cpu_context = renderer->GetRenderWindow().CreateSharedContext();
+        }
         cpu_context->MakeCurrent();
         cpu_context->MakeCurrent();
     }
     }
 
 

+ 6 - 4
src/video_core/renderer_opengl/gl_device.cpp

@@ -112,7 +112,7 @@ bool IsASTCSupported() {
 }
 }
 } // Anonymous namespace
 } // Anonymous namespace
 
 
-Device::Device() {
+Device::Device(Core::Frontend::EmuWindow& emu_window) {
     if (!GLAD_GL_VERSION_4_6) {
     if (!GLAD_GL_VERSION_4_6) {
         LOG_ERROR(Render_OpenGL, "OpenGL 4.6 is not available");
         LOG_ERROR(Render_OpenGL, "OpenGL 4.6 is not available");
         throw std::runtime_error{"Insufficient version"};
         throw std::runtime_error{"Insufficient version"};
@@ -126,9 +126,9 @@ Device::Device() {
     const bool is_intel = vendor_name == "Intel";
     const bool is_intel = vendor_name == "Intel";
 
 
 #ifdef __unix__
 #ifdef __unix__
-    const bool is_linux = true;
+    constexpr bool is_linux = true;
 #else
 #else
-    const bool is_linux = false;
+    constexpr bool is_linux = false;
 #endif
 #endif
 
 
     bool disable_fast_buffer_sub_data = false;
     bool disable_fast_buffer_sub_data = false;
@@ -193,9 +193,11 @@ Device::Device() {
         }
         }
     }
     }
 
 
+    strict_context_required = emu_window.StrictContextRequired();
     // Blocks AMD and Intel OpenGL drivers on Windows from using asynchronous shader compilation.
     // Blocks AMD and Intel OpenGL drivers on Windows from using asynchronous shader compilation.
+    // Blocks EGL on Wayland from using asynchronous shader compilation.
     use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue() &&
     use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue() &&
-                               !(is_amd || (is_intel && !is_linux));
+                               !(is_amd || (is_intel && !is_linux)) && !strict_context_required;
     use_driver_cache = is_nvidia;
     use_driver_cache = is_nvidia;
 
 
     LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);
     LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);

+ 7 - 1
src/video_core/renderer_opengl/gl_device.h

@@ -5,6 +5,7 @@
 
 
 #include <cstddef>
 #include <cstddef>
 #include "common/common_types.h"
 #include "common/common_types.h"
+#include "core/frontend/emu_window.h"
 #include "shader_recompiler/stage.h"
 #include "shader_recompiler/stage.h"
 
 
 namespace Settings {
 namespace Settings {
@@ -15,7 +16,7 @@ namespace OpenGL {
 
 
 class Device {
 class Device {
 public:
 public:
-    explicit Device();
+    explicit Device(Core::Frontend::EmuWindow& emu_window);
 
 
     [[nodiscard]] std::string GetVendorName() const;
     [[nodiscard]] std::string GetVendorName() const;
 
 
@@ -173,6 +174,10 @@ public:
         return can_report_memory;
         return can_report_memory;
     }
     }
 
 
+    bool StrictContextRequired() const {
+        return strict_context_required;
+    }
+
 private:
 private:
     static bool TestVariableAoffi();
     static bool TestVariableAoffi();
     static bool TestPreciseBug();
     static bool TestPreciseBug();
@@ -216,6 +221,7 @@ private:
     bool has_cbuf_ftou_bug{};
     bool has_cbuf_ftou_bug{};
     bool has_bool_ref_bug{};
     bool has_bool_ref_bug{};
     bool can_report_memory{};
     bool can_report_memory{};
+    bool strict_context_required{};
 
 
     std::string vendor_name;
     std::string vendor_name;
 };
 };

+ 45 - 31
src/video_core/renderer_opengl/gl_shader_cache.cpp

@@ -174,6 +174,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
       texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_},
       texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_},
       state_tracker{state_tracker_}, shader_notify{shader_notify_},
       state_tracker{state_tracker_}, shader_notify{shader_notify_},
       use_asynchronous_shaders{device.UseAsynchronousShaders()},
       use_asynchronous_shaders{device.UseAsynchronousShaders()},
+      strict_context_required{device.StrictContextRequired()},
       profile{
       profile{
           .supported_spirv = 0x00010000,
           .supported_spirv = 0x00010000,
 
 
@@ -255,9 +256,14 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
     }
     }
     shader_cache_filename = base_dir / "opengl.bin";
     shader_cache_filename = base_dir / "opengl.bin";
 
 
-    if (!workers) {
+    if (!workers && !strict_context_required) {
         workers = CreateWorkers();
         workers = CreateWorkers();
     }
     }
+    std::optional<Context> strict_context;
+    if (strict_context_required) {
+        strict_context.emplace(emu_window);
+    }
+
     struct {
     struct {
         std::mutex mutex;
         std::mutex mutex;
         size_t total{};
         size_t total{};
@@ -265,44 +271,49 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
         bool has_loaded{};
         bool has_loaded{};
     } state;
     } state;
 
 
+    const auto queue_work{[&](Common::UniqueFunction<void, Context*>&& work) {
+        if (strict_context_required) {
+            work(&strict_context.value());
+        } else {
+            workers->QueueWork(std::move(work));
+        }
+    }};
     const auto load_compute{[&](std::ifstream& file, FileEnvironment env) {
     const auto load_compute{[&](std::ifstream& file, FileEnvironment env) {
         ComputePipelineKey key;
         ComputePipelineKey key;
         file.read(reinterpret_cast<char*>(&key), sizeof(key));
         file.read(reinterpret_cast<char*>(&key), sizeof(key));
-        workers->QueueWork(
-            [this, key, env = std::move(env), &state, &callback](Context* ctx) mutable {
-                ctx->pools.ReleaseContents();
-                auto pipeline{CreateComputePipeline(ctx->pools, key, env)};
-                std::scoped_lock lock{state.mutex};
-                if (pipeline) {
-                    compute_cache.emplace(key, std::move(pipeline));
-                }
-                ++state.built;
-                if (state.has_loaded) {
-                    callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
-                }
-            });
+        queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable {
+            ctx->pools.ReleaseContents();
+            auto pipeline{CreateComputePipeline(ctx->pools, key, env)};
+            std::scoped_lock lock{state.mutex};
+            if (pipeline) {
+                compute_cache.emplace(key, std::move(pipeline));
+            }
+            ++state.built;
+            if (state.has_loaded) {
+                callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
+            }
+        });
         ++state.total;
         ++state.total;
     }};
     }};
     const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) {
     const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) {
         GraphicsPipelineKey key;
         GraphicsPipelineKey key;
         file.read(reinterpret_cast<char*>(&key), sizeof(key));
         file.read(reinterpret_cast<char*>(&key), sizeof(key));
-        workers->QueueWork(
-            [this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable {
-                boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
-                for (auto& env : envs) {
-                    env_ptrs.push_back(&env);
-                }
-                ctx->pools.ReleaseContents();
-                auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)};
-                std::scoped_lock lock{state.mutex};
-                if (pipeline) {
-                    graphics_cache.emplace(key, std::move(pipeline));
-                }
-                ++state.built;
-                if (state.has_loaded) {
-                    callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
-                }
-            });
+        queue_work([this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable {
+            boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
+            for (auto& env : envs) {
+                env_ptrs.push_back(&env);
+            }
+            ctx->pools.ReleaseContents();
+            auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)};
+            std::scoped_lock lock{state.mutex};
+            if (pipeline) {
+                graphics_cache.emplace(key, std::move(pipeline));
+            }
+            ++state.built;
+            if (state.has_loaded) {
+                callback(VideoCore::LoadCallbackStage::Build, state.built, state.total);
+            }
+        });
         ++state.total;
         ++state.total;
     }};
     }};
     LoadPipelines(stop_loading, shader_cache_filename, CACHE_VERSION, load_compute, load_graphics);
     LoadPipelines(stop_loading, shader_cache_filename, CACHE_VERSION, load_compute, load_graphics);
@@ -314,6 +325,9 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
     state.has_loaded = true;
     state.has_loaded = true;
     lock.unlock();
     lock.unlock();
 
 
+    if (strict_context_required) {
+        return;
+    }
     workers->WaitForRequests(stop_loading);
     workers->WaitForRequests(stop_loading);
     if (!use_asynchronous_shaders) {
     if (!use_asynchronous_shaders) {
         workers.reset();
         workers.reset();

+ 1 - 0
src/video_core/renderer_opengl/gl_shader_cache.h

@@ -69,6 +69,7 @@ private:
     StateTracker& state_tracker;
     StateTracker& state_tracker;
     VideoCore::ShaderNotify& shader_notify;
     VideoCore::ShaderNotify& shader_notify;
     const bool use_asynchronous_shaders;
     const bool use_asynchronous_shaders;
+    const bool strict_context_required;
 
 
     GraphicsPipelineKey graphics_key{};
     GraphicsPipelineKey graphics_key{};
     GraphicsPipeline* current_pipeline{};
     GraphicsPipeline* current_pipeline{};

+ 2 - 2
src/video_core/renderer_opengl/renderer_opengl.cpp

@@ -140,8 +140,8 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
                                Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
                                Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
                                std::unique_ptr<Core::Frontend::GraphicsContext> context_)
                                std::unique_ptr<Core::Frontend::GraphicsContext> context_)
     : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
     : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
-      emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, state_tracker{},
-      program_manager{device},
+      emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, device{emu_window_},
+      state_tracker{}, program_manager{device},
       rasterizer(emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker) {
       rasterizer(emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker) {
     if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
     if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
         glEnable(GL_DEBUG_OUTPUT);
         glEnable(GL_DEBUG_OUTPUT);

+ 8 - 6
src/video_core/renderer_vulkan/renderer_vulkan.cpp

@@ -139,23 +139,25 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
     RenderScreenshot(*framebuffer, use_accelerated);
     RenderScreenshot(*framebuffer, use_accelerated);
 
 
     bool has_been_recreated = false;
     bool has_been_recreated = false;
-    const auto recreate_swapchain = [&] {
+    const auto recreate_swapchain = [&](u32 width, u32 height) {
         if (!has_been_recreated) {
         if (!has_been_recreated) {
             has_been_recreated = true;
             has_been_recreated = true;
             scheduler.Finish();
             scheduler.Finish();
         }
         }
-        const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout();
-        swapchain.Create(layout.width, layout.height, is_srgb);
+        swapchain.Create(width, height, is_srgb);
     };
     };
-    if (swapchain.NeedsRecreation(is_srgb)) {
-        recreate_swapchain();
+
+    const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout();
+    if (swapchain.NeedsRecreation(is_srgb) || swapchain.GetWidth() != layout.width ||
+        swapchain.GetHeight() != layout.height) {
+        recreate_swapchain(layout.width, layout.height);
     }
     }
     bool is_outdated;
     bool is_outdated;
     do {
     do {
         swapchain.AcquireNextImage();
         swapchain.AcquireNextImage();
         is_outdated = swapchain.IsOutDated();
         is_outdated = swapchain.IsOutDated();
         if (is_outdated) {
         if (is_outdated) {
-            recreate_swapchain();
+            recreate_swapchain(layout.width, layout.height);
         }
         }
     } while (is_outdated);
     } while (is_outdated);
     if (has_been_recreated) {
     if (has_been_recreated) {

+ 8 - 7
src/video_core/renderer_vulkan/vk_swapchain.cpp

@@ -67,17 +67,19 @@ VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 wi
 
 
 } // Anonymous namespace
 } // Anonymous namespace
 
 
-Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, u32 width,
-                     u32 height, bool srgb)
+Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_,
+                     u32 width_, u32 height_, bool srgb)
     : surface{surface_}, device{device_}, scheduler{scheduler_} {
     : surface{surface_}, device{device_}, scheduler{scheduler_} {
-    Create(width, height, srgb);
+    Create(width_, height_, srgb);
 }
 }
 
 
 Swapchain::~Swapchain() = default;
 Swapchain::~Swapchain() = default;
 
 
-void Swapchain::Create(u32 width, u32 height, bool srgb) {
+void Swapchain::Create(u32 width_, u32 height_, bool srgb) {
     is_outdated = false;
     is_outdated = false;
     is_suboptimal = false;
     is_suboptimal = false;
+    width = width_;
+    height = height_;
 
 
     const auto physical_device = device.GetPhysical();
     const auto physical_device = device.GetPhysical();
     const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)};
     const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)};
@@ -88,7 +90,7 @@ void Swapchain::Create(u32 width, u32 height, bool srgb) {
     device.GetLogical().WaitIdle();
     device.GetLogical().WaitIdle();
     Destroy();
     Destroy();
 
 
-    CreateSwapchain(capabilities, width, height, srgb);
+    CreateSwapchain(capabilities, srgb);
     CreateSemaphores();
     CreateSemaphores();
     CreateImageViews();
     CreateImageViews();
 
 
@@ -148,8 +150,7 @@ void Swapchain::Present(VkSemaphore render_semaphore) {
     }
     }
 }
 }
 
 
-void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height,
-                                bool srgb) {
+void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb) {
     const auto physical_device{device.GetPhysical()};
     const auto physical_device{device.GetPhysical()};
     const auto formats{physical_device.GetSurfaceFormatsKHR(surface)};
     const auto formats{physical_device.GetSurfaceFormatsKHR(surface)};
     const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)};
     const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)};

+ 12 - 2
src/video_core/renderer_vulkan/vk_swapchain.h

@@ -80,9 +80,16 @@ public:
         return *present_semaphores[frame_index];
         return *present_semaphores[frame_index];
     }
     }
 
 
+    u32 GetWidth() const {
+        return width;
+    }
+
+    u32 GetHeight() const {
+        return height;
+    }
+
 private:
 private:
-    void CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height,
-                         bool srgb);
+    void CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb);
     void CreateSemaphores();
     void CreateSemaphores();
     void CreateImageViews();
     void CreateImageViews();
 
 
@@ -105,6 +112,9 @@ private:
     std::vector<u64> resource_ticks;
     std::vector<u64> resource_ticks;
     std::vector<vk::Semaphore> present_semaphores;
     std::vector<vk::Semaphore> present_semaphores;
 
 
+    u32 width;
+    u32 height;
+
     u32 image_index{};
     u32 image_index{};
     u32 frame_index{};
     u32 frame_index{};
 
 

+ 10 - 2
src/yuzu/bootmanager.cpp

@@ -61,8 +61,6 @@ void EmuThread::run() {
 
 
     // Main process has been loaded. Make the context current to this thread and begin GPU and CPU
     // Main process has been loaded. Make the context current to this thread and begin GPU and CPU
     // execution.
     // execution.
-    gpu.Start();
-
     gpu.ObtainContext();
     gpu.ObtainContext();
 
 
     emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
     emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
@@ -77,6 +75,7 @@ void EmuThread::run() {
     emit LoadProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
     emit LoadProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
 
 
     gpu.ReleaseContext();
     gpu.ReleaseContext();
+    gpu.Start();
 
 
     system.GetCpuManager().OnGpuReady();
     system.GetCpuManager().OnGpuReady();
 
 
@@ -224,6 +223,7 @@ class RenderWidget : public QWidget {
 public:
 public:
     explicit RenderWidget(GRenderWindow* parent) : QWidget(parent), render_window(parent) {
     explicit RenderWidget(GRenderWindow* parent) : QWidget(parent), render_window(parent) {
         setAttribute(Qt::WA_NativeWindow);
         setAttribute(Qt::WA_NativeWindow);
+        setAttribute(Qt::WA_DontCreateNativeAncestors);
         setAttribute(Qt::WA_PaintOnScreen);
         setAttribute(Qt::WA_PaintOnScreen);
     }
     }
 
 
@@ -314,6 +314,8 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
     input_subsystem->Initialize();
     input_subsystem->Initialize();
     this->setMouseTracking(true);
     this->setMouseTracking(true);
 
 
+    strict_context_required = QGuiApplication::platformName() == QStringLiteral("wayland");
+
     connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete);
     connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete);
     connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram,
     connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram,
             Qt::QueuedConnection);
             Qt::QueuedConnection);
@@ -952,6 +954,12 @@ void GRenderWindow::OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal
 
 
 bool GRenderWindow::InitializeOpenGL() {
 bool GRenderWindow::InitializeOpenGL() {
 #ifdef HAS_OPENGL
 #ifdef HAS_OPENGL
+    if (!QOpenGLContext::supportsThreadedOpenGL()) {
+        QMessageBox::warning(this, tr("OpenGL not available!"),
+                             tr("OpenGL shared contexts are not supported."));
+        return false;
+    }
+
     // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground,
     // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground,
     // WA_DontShowOnScreen, WA_DeleteOnClose
     // WA_DontShowOnScreen, WA_DeleteOnClose
     auto child = new OpenGLRenderWidget(this);
     auto child = new OpenGLRenderWidget(this);

+ 9 - 4
src/yuzu/main.cpp

@@ -2915,9 +2915,14 @@ static QScreen* GuessCurrentScreen(QWidget* window) {
         });
         });
 }
 }
 
 
+bool GMainWindow::UsingExclusiveFullscreen() {
+    return Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive ||
+           QGuiApplication::platformName() == QStringLiteral("wayland");
+}
+
 void GMainWindow::ShowFullscreen() {
 void GMainWindow::ShowFullscreen() {
-    const auto show_fullscreen = [](QWidget* window) {
-        if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) {
+    const auto show_fullscreen = [this](QWidget* window) {
+        if (UsingExclusiveFullscreen()) {
             window->showFullScreen();
             window->showFullScreen();
             return;
             return;
         }
         }
@@ -2945,7 +2950,7 @@ void GMainWindow::ShowFullscreen() {
 
 
 void GMainWindow::HideFullscreen() {
 void GMainWindow::HideFullscreen() {
     if (ui->action_Single_Window_Mode->isChecked()) {
     if (ui->action_Single_Window_Mode->isChecked()) {
-        if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) {
+        if (UsingExclusiveFullscreen()) {
             showNormal();
             showNormal();
             restoreGeometry(UISettings::values.geometry);
             restoreGeometry(UISettings::values.geometry);
         } else {
         } else {
@@ -2959,7 +2964,7 @@ void GMainWindow::HideFullscreen() {
         statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
         statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
         ui->menubar->show();
         ui->menubar->show();
     } else {
     } else {
-        if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) {
+        if (UsingExclusiveFullscreen()) {
             render_window->showNormal();
             render_window->showNormal();
             render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
             render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
         } else {
         } else {

+ 1 - 0
src/yuzu/main.h

@@ -320,6 +320,7 @@ private slots:
     void OnDisplayTitleBars(bool);
     void OnDisplayTitleBars(bool);
     void InitializeHotkeys();
     void InitializeHotkeys();
     void ToggleFullscreen();
     void ToggleFullscreen();
+    bool UsingExclusiveFullscreen();
     void ShowFullscreen();
     void ShowFullscreen();
     void HideFullscreen();
     void HideFullscreen();
     void ToggleWindowMode();
     void ToggleWindowMode();

+ 1 - 1
src/yuzu_cmd/emu_window/emu_window_sdl2.cpp

@@ -115,7 +115,7 @@ bool EmuWindow_SDL2::IsShown() const {
 
 
 void EmuWindow_SDL2::OnResize() {
 void EmuWindow_SDL2::OnResize() {
     int width, height;
     int width, height;
-    SDL_GetWindowSize(render_window, &width, &height);
+    SDL_GL_GetDrawableSize(render_window, &width, &height);
     UpdateCurrentFramebufferLayout(width, height);
     UpdateCurrentFramebufferLayout(width, height);
 }
 }
 
 

+ 2 - 0
src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp

@@ -104,6 +104,8 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste
         exit(1);
         exit(1);
     }
     }
 
 
+    strict_context_required = strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0;
+
     SetWindowIcon();
     SetWindowIcon();
 
 
     if (fullscreen) {
     if (fullscreen) {