Merge pull request #6412 from GPUCode/wayland-oops

Port yuzu-emu/yuzu#7410: "Wayland fixes"
This commit is contained in:
SachinVin 2023-04-08 16:51:56 +05:30 committed by GitHub
commit e4e9fb4aed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 25 deletions

View file

@ -84,7 +84,7 @@ void EmuWindow_SDL2::RequestClose() {
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);
} }

View file

@ -82,6 +82,8 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(bool fullscreen, bool is_secondary)
exit(1); exit(1);
} }
strict_context_required = std::strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0;
dummy_window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0, dummy_window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0,
SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL); SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);

View file

@ -40,6 +40,8 @@
#include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformnativeinterface.h>
#endif #endif
static Frontend::WindowSystemType GetWindowSystemType();
EmuThread::EmuThread(Frontend::GraphicsContext& core_context) : core_context(core_context) {} EmuThread::EmuThread(Frontend::GraphicsContext& core_context) : core_context(core_context) {}
EmuThread::~EmuThread() = default; EmuThread::~EmuThread() = default;
@ -242,6 +244,9 @@ public:
: RenderWidget(parent), is_secondary(is_secondary) { : RenderWidget(parent), is_secondary(is_secondary) {
setAttribute(Qt::WA_NativeWindow); setAttribute(Qt::WA_NativeWindow);
setAttribute(Qt::WA_PaintOnScreen); setAttribute(Qt::WA_PaintOnScreen);
if (GetWindowSystemType() == Frontend::WindowSystemType::Wayland) {
setAttribute(Qt::WA_DontCreateNativeAncestors);
}
windowHandle()->setSurfaceType(QWindow::OpenGLSurface); windowHandle()->setSurfaceType(QWindow::OpenGLSurface);
} }
@ -401,6 +406,7 @@ GRenderWindow::GRenderWindow(QWidget* parent_, EmuThread* emu_thread, bool is_se
setLayout(layout); setLayout(layout);
this->setMouseTracking(true); this->setMouseTracking(true);
strict_context_required = QGuiApplication::platformName() == QStringLiteral("wayland");
GMainWindow* parent = GetMainWindow(); GMainWindow* parent = GetMainWindow();
connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete); connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete);
@ -660,6 +666,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, is_secondary); auto child = new OpenGLRenderWidget(this, is_secondary);

View file

@ -203,6 +203,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.
@ -268,6 +272,7 @@ protected:
} }
bool is_secondary{}; bool is_secondary{};
bool strict_context_required{};
WindowSystemInfo window_info; WindowSystemInfo window_info;
private: private:

View file

@ -7,6 +7,7 @@
#include <thread> #include <thread>
#include <unordered_map> #include <unordered_map>
#include <variant> #include <variant>
#include "common/scope_exit.h"
#include "video_core/renderer_opengl/gl_driver.h" #include "video_core/renderer_opengl/gl_driver.h"
#include "video_core/renderer_opengl/gl_resource_manager.h" #include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_shader_disk_cache.h" #include "video_core/renderer_opengl/gl_shader_disk_cache.h"
@ -367,7 +368,9 @@ public:
ShaderProgramManager::ShaderProgramManager(Frontend::EmuWindow& emu_window_, const Driver& driver_, ShaderProgramManager::ShaderProgramManager(Frontend::EmuWindow& emu_window_, const Driver& driver_,
bool separable) bool separable)
: impl(std::make_unique<Impl>(separable)), emu_window{emu_window_}, driver{driver_} {} : emu_window{emu_window_}, driver{driver_},
strict_context_required{emu_window.StrictContextRequired()}, impl{std::make_unique<Impl>(
separable)} {}
ShaderProgramManager::~ShaderProgramManager() = default; ShaderProgramManager::~ShaderProgramManager() = default;
@ -622,8 +625,8 @@ void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading,
compilation_failed = false; compilation_failed = false;
std::size_t built_shaders = 0; // It doesn't have be atomic since it's used behind a mutex std::size_t built_shaders = 0; // It doesn't have be atomic since it's used behind a mutex
const auto LoadRawSepareble = [&](Frontend::GraphicsContext* context, std::size_t begin, const auto LoadRawSepareble = [&](std::size_t begin, std::size_t end,
std::size_t end) { Frontend::GraphicsContext* context = nullptr) {
const auto scope = context->Acquire(); const auto scope = context->Acquire();
for (std::size_t i = begin; i < end; ++i) { for (std::size_t i = begin; i < end; ++i) {
if (stop_loading || compilation_failed) { if (stop_loading || compilation_failed) {
@ -683,6 +686,7 @@ void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading,
} }
}; };
if (!strict_context_required) {
const std::size_t num_workers{std::max(1U, std::thread::hardware_concurrency())}; const std::size_t num_workers{std::max(1U, std::thread::hardware_concurrency())};
const std::size_t bucket_size{load_raws_size / num_workers}; const std::size_t bucket_size{load_raws_size / num_workers};
std::vector<std::unique_ptr<Frontend::GraphicsContext>> contexts(num_workers); std::vector<std::unique_ptr<Frontend::GraphicsContext>> contexts(num_workers);
@ -698,12 +702,16 @@ void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading,
contexts[i] = emu_window.CreateSharedContext(); contexts[i] = emu_window.CreateSharedContext();
// Release the context, so it can be immediately used by the spawned thread // Release the context, so it can be immediately used by the spawned thread
contexts[i]->DoneCurrent(); contexts[i]->DoneCurrent();
threads[i] = std::thread(LoadRawSepareble, contexts[i].get(), start, end); threads[i] = std::thread(LoadRawSepareble, start, end, contexts[i].get());
} }
for (auto& thread : threads) { for (auto& thread : threads) {
thread.join(); thread.join();
} }
emu_window.RestoreContext(); emu_window.RestoreContext();
} else {
const auto dummy_context{std::make_unique<Frontend::GraphicsContext>()};
LoadRawSepareble(0, load_raws_size, dummy_context.get());
}
if (compilation_failed) { if (compilation_failed) {
disk_cache.InvalidateAll(); disk_cache.InvalidateAll();

View file

@ -46,10 +46,10 @@ public:
void ApplyTo(OpenGLState& state); void ApplyTo(OpenGLState& state);
private: private:
class Impl;
std::unique_ptr<Impl> impl;
Frontend::EmuWindow& emu_window; Frontend::EmuWindow& emu_window;
const Driver& driver; const Driver& driver;
bool strict_context_required;
class Impl;
std::unique_ptr<Impl> impl;
}; };
} // namespace OpenGL } // namespace OpenGL