Merge pull request #6412 from GPUCode/wayland-oops
Port yuzu-emu/yuzu#7410: "Wayland fixes"
This commit is contained in:
commit
e4e9fb4aed
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,27 +686,32 @@ void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::size_t num_workers{std::max(1U, std::thread::hardware_concurrency())};
|
if (!strict_context_required) {
|
||||||
const std::size_t bucket_size{load_raws_size / num_workers};
|
const std::size_t num_workers{std::max(1U, std::thread::hardware_concurrency())};
|
||||||
std::vector<std::unique_ptr<Frontend::GraphicsContext>> contexts(num_workers);
|
const std::size_t bucket_size{load_raws_size / num_workers};
|
||||||
std::vector<std::thread> threads(num_workers);
|
std::vector<std::unique_ptr<Frontend::GraphicsContext>> contexts(num_workers);
|
||||||
|
std::vector<std::thread> threads(num_workers);
|
||||||
|
|
||||||
emu_window.SaveContext();
|
emu_window.SaveContext();
|
||||||
for (std::size_t i = 0; i < num_workers; ++i) {
|
for (std::size_t i = 0; i < num_workers; ++i) {
|
||||||
const bool is_last_worker = i + 1 == num_workers;
|
const bool is_last_worker = i + 1 == num_workers;
|
||||||
const std::size_t start{bucket_size * i};
|
const std::size_t start{bucket_size * i};
|
||||||
const std::size_t end{is_last_worker ? load_raws_size : start + bucket_size};
|
const std::size_t end{is_last_worker ? load_raws_size : start + bucket_size};
|
||||||
|
|
||||||
// On some platforms the shared context has to be created from the GUI thread
|
// On some platforms the shared context has to be created from the GUI thread
|
||||||
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) {
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
emu_window.RestoreContext();
|
||||||
|
} else {
|
||||||
|
const auto dummy_context{std::make_unique<Frontend::GraphicsContext>()};
|
||||||
|
LoadRawSepareble(0, load_raws_size, dummy_context.get());
|
||||||
}
|
}
|
||||||
for (auto& thread : threads) {
|
|
||||||
thread.join();
|
|
||||||
}
|
|
||||||
emu_window.RestoreContext();
|
|
||||||
|
|
||||||
if (compilation_failed) {
|
if (compilation_failed) {
|
||||||
disk_cache.InvalidateAll();
|
disk_cache.InvalidateAll();
|
||||||
|
|
|
@ -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
|
||||||
|
|
Reference in New Issue