summaryrefslogtreecommitdiff
path: root/src/yuzu
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu')
-rw-r--r--src/yuzu/CMakeLists.txt2
-rw-r--r--src/yuzu/bootmanager.cpp208
-rw-r--r--src/yuzu/bootmanager.h29
-rw-r--r--src/yuzu/configuration/config.cpp10
-rw-r--r--src/yuzu/configuration/configure_general.cpp4
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp3
-rw-r--r--src/yuzu/configuration/configure_graphics.ui7
-rw-r--r--src/yuzu/debugger/graphics/graphics_surface.cpp516
-rw-r--r--src/yuzu/debugger/graphics/graphics_surface.h96
-rw-r--r--src/yuzu/game_list.cpp5
-rw-r--r--src/yuzu/main.cpp45
-rw-r--r--src/yuzu/main.h6
-rw-r--r--src/yuzu/ui_settings.h4
13 files changed, 209 insertions, 726 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 732a1bf89..2eb86d6e5 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -56,8 +56,6 @@ add_executable(yuzu
debugger/graphics/graphics_breakpoints.cpp
debugger/graphics/graphics_breakpoints.h
debugger/graphics/graphics_breakpoints_p.h
- debugger/graphics/graphics_surface.cpp
- debugger/graphics/graphics_surface.h
debugger/console.cpp
debugger/console.h
debugger/profiler.cpp
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 7438fbc0a..c29f2d2dc 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -1,6 +1,13 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
#include <QApplication>
#include <QHBoxLayout>
#include <QKeyEvent>
+#include <QOffscreenSurface>
+#include <QOpenGLWindow>
+#include <QPainter>
#include <QScreen>
#include <QWindow>
#include <fmt/format.h>
@@ -82,13 +89,36 @@ void EmuThread::run() {
render_window->moveContext();
}
+class GGLContext : public Core::Frontend::GraphicsContext {
+public:
+ explicit GGLContext(QOpenGLContext* shared_context) : surface() {
+ context = std::make_unique<QOpenGLContext>(shared_context);
+ surface.setFormat(shared_context->format());
+ surface.create();
+ }
+
+ void MakeCurrent() override {
+ context->makeCurrent(&surface);
+ }
+
+ void DoneCurrent() override {
+ context->doneCurrent();
+ }
+
+ void SwapBuffers() override {}
+
+private:
+ std::unique_ptr<QOpenGLContext> context;
+ QOffscreenSurface surface;
+};
+
// This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL
// context.
// The corresponding functionality is handled in EmuThread instead
-class GGLWidgetInternal : public QGLWidget {
+class GGLWidgetInternal : public QOpenGLWindow {
public:
- GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent)
- : QGLWidget(fmt, parent), parent(parent) {}
+ GGLWidgetInternal(GRenderWindow* parent, QOpenGLContext* shared_context)
+ : QOpenGLWindow(shared_context), parent(parent) {}
void paintEvent(QPaintEvent* ev) override {
if (do_painting) {
@@ -101,9 +131,51 @@ public:
parent->OnFramebufferSizeChanged();
}
+ void keyPressEvent(QKeyEvent* event) override {
+ InputCommon::GetKeyboard()->PressKey(event->key());
+ }
+
+ void keyReleaseEvent(QKeyEvent* event) override {
+ InputCommon::GetKeyboard()->ReleaseKey(event->key());
+ }
+
+ void mousePressEvent(QMouseEvent* event) override {
+ if (event->source() == Qt::MouseEventSynthesizedBySystem)
+ return; // touch input is handled in TouchBeginEvent
+
+ const auto pos{event->pos()};
+ if (event->button() == Qt::LeftButton) {
+ const auto [x, y] = parent->ScaleTouch(pos);
+ parent->TouchPressed(x, y);
+ } else if (event->button() == Qt::RightButton) {
+ InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y());
+ }
+ }
+
+ void mouseMoveEvent(QMouseEvent* event) override {
+ if (event->source() == Qt::MouseEventSynthesizedBySystem)
+ return; // touch input is handled in TouchUpdateEvent
+
+ const auto pos{event->pos()};
+ const auto [x, y] = parent->ScaleTouch(pos);
+ parent->TouchMoved(x, y);
+ InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y());
+ }
+
+ void mouseReleaseEvent(QMouseEvent* event) override {
+ if (event->source() == Qt::MouseEventSynthesizedBySystem)
+ return; // touch input is handled in TouchEndEvent
+
+ if (event->button() == Qt::LeftButton)
+ parent->TouchReleased();
+ else if (event->button() == Qt::RightButton)
+ InputCommon::GetMotionEmu()->EndTilt();
+ }
+
void DisablePainting() {
do_painting = false;
}
+
void EnablePainting() {
do_painting = true;
}
@@ -114,7 +186,7 @@ private:
};
GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread)
- : QWidget(parent), child(nullptr), emu_thread(emu_thread) {
+ : QWidget(parent), child(nullptr), context(nullptr), emu_thread(emu_thread) {
setWindowTitle(QStringLiteral("yuzu %1 | %2-%3")
.arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc));
@@ -137,19 +209,19 @@ void GRenderWindow::moveContext() {
auto thread = (QThread::currentThread() == qApp->thread() && emu_thread != nullptr)
? emu_thread
: qApp->thread();
- child->context()->moveToThread(thread);
+ context->moveToThread(thread);
}
void GRenderWindow::SwapBuffers() {
- // In our multi-threaded QGLWidget use case we shouldn't need to call `makeCurrent`,
+ // In our multi-threaded QWidget use case we shouldn't need to call `makeCurrent`,
// since we never call `doneCurrent` in this thread.
// However:
// - The Qt debug runtime prints a bogus warning on the console if `makeCurrent` wasn't called
// since the last time `swapBuffers` was executed;
// - On macOS, if `makeCurrent` isn't called explicitely, resizing the buffer breaks.
- child->makeCurrent();
+ context->makeCurrent(child);
- child->swapBuffers();
+ context->swapBuffers(child);
if (!first_frame) {
emit FirstFrameDisplayed();
first_frame = true;
@@ -157,11 +229,11 @@ void GRenderWindow::SwapBuffers() {
}
void GRenderWindow::MakeCurrent() {
- child->makeCurrent();
+ context->makeCurrent(child);
}
void GRenderWindow::DoneCurrent() {
- child->doneCurrent();
+ context->doneCurrent();
}
void GRenderWindow::PollEvents() {}
@@ -174,14 +246,26 @@ void GRenderWindow::PollEvents() {}
void GRenderWindow::OnFramebufferSizeChanged() {
// Screen changes potentially incur a change in screen DPI, hence we should update the
// framebuffer size
- qreal pixelRatio = windowPixelRatio();
+ qreal pixelRatio = GetWindowPixelRatio();
unsigned width = child->QPaintDevice::width() * pixelRatio;
unsigned height = child->QPaintDevice::height() * pixelRatio;
UpdateCurrentFramebufferLayout(width, height);
}
+void GRenderWindow::ForwardKeyPressEvent(QKeyEvent* event) {
+ if (child) {
+ child->keyPressEvent(event);
+ }
+}
+
+void GRenderWindow::ForwardKeyReleaseEvent(QKeyEvent* event) {
+ if (child) {
+ child->keyReleaseEvent(event);
+ }
+}
+
void GRenderWindow::BackupGeometry() {
- geometry = ((QGLWidget*)this)->saveGeometry();
+ geometry = ((QWidget*)this)->saveGeometry();
}
void GRenderWindow::RestoreGeometry() {
@@ -199,18 +283,18 @@ QByteArray GRenderWindow::saveGeometry() {
// If we are a top-level widget, store the current geometry
// otherwise, store the last backup
if (parent() == nullptr)
- return ((QGLWidget*)this)->saveGeometry();
+ return ((QWidget*)this)->saveGeometry();
else
return geometry;
}
-qreal GRenderWindow::windowPixelRatio() const {
+qreal GRenderWindow::GetWindowPixelRatio() const {
// windowHandle() might not be accessible until the window is displayed to screen.
return windowHandle() ? windowHandle()->screen()->devicePixelRatio() : 1.0f;
}
std::pair<unsigned, unsigned> GRenderWindow::ScaleTouch(const QPointF pos) const {
- const qreal pixel_ratio = windowPixelRatio();
+ const qreal pixel_ratio = GetWindowPixelRatio();
return {static_cast<unsigned>(std::max(std::round(pos.x() * pixel_ratio), qreal{0.0})),
static_cast<unsigned>(std::max(std::round(pos.y() * pixel_ratio), qreal{0.0}))};
}
@@ -220,47 +304,6 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
QWidget::closeEvent(event);
}
-void GRenderWindow::keyPressEvent(QKeyEvent* event) {
- InputCommon::GetKeyboard()->PressKey(event->key());
-}
-
-void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
- InputCommon::GetKeyboard()->ReleaseKey(event->key());
-}
-
-void GRenderWindow::mousePressEvent(QMouseEvent* event) {
- if (event->source() == Qt::MouseEventSynthesizedBySystem)
- return; // touch input is handled in TouchBeginEvent
-
- auto pos = event->pos();
- if (event->button() == Qt::LeftButton) {
- const auto [x, y] = ScaleTouch(pos);
- this->TouchPressed(x, y);
- } else if (event->button() == Qt::RightButton) {
- InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y());
- }
-}
-
-void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
- if (event->source() == Qt::MouseEventSynthesizedBySystem)
- return; // touch input is handled in TouchUpdateEvent
-
- auto pos = event->pos();
- const auto [x, y] = ScaleTouch(pos);
- this->TouchMoved(x, y);
- InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y());
-}
-
-void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
- if (event->source() == Qt::MouseEventSynthesizedBySystem)
- return; // touch input is handled in TouchEndEvent
-
- if (event->button() == Qt::LeftButton)
- this->TouchReleased();
- else if (event->button() == Qt::RightButton)
- InputCommon::GetMotionEmu()->EndTilt();
-}
-
void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) {
// TouchBegin always has exactly one touch point, so take the .first()
const auto [x, y] = ScaleTouch(event->touchPoints().first().pos());
@@ -313,35 +356,60 @@ void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) {
NotifyClientAreaSizeChanged(std::make_pair(width, height));
}
+std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const {
+ return std::make_unique<GGLContext>(shared_context.get());
+}
+
void GRenderWindow::InitRenderTarget() {
- if (child) {
- delete child;
- }
+ shared_context.reset();
+ context.reset();
- if (layout()) {
- delete layout();
- }
+ delete child;
+ child = nullptr;
+
+ delete container;
+ container = nullptr;
+
+ delete layout();
first_frame = false;
// TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground,
// WA_DontShowOnScreen, WA_DeleteOnClose
- QGLFormat fmt;
+ QSurfaceFormat fmt;
fmt.setVersion(4, 3);
- fmt.setProfile(QGLFormat::CoreProfile);
+ fmt.setProfile(QSurfaceFormat::CoreProfile);
+ // TODO: expose a setting for buffer value (ie default/single/double/triple)
+ fmt.setSwapBehavior(QSurfaceFormat::DefaultSwapBehavior);
+ shared_context = std::make_unique<QOpenGLContext>();
+ shared_context->setFormat(fmt);
+ shared_context->create();
+ context = std::make_unique<QOpenGLContext>();
+ context->setShareContext(shared_context.get());
+ context->setFormat(fmt);
+ context->create();
fmt.setSwapInterval(false);
- // Requests a forward-compatible context, which is required to get a 3.2+ context on OS X
- fmt.setOption(QGL::NoDeprecatedFunctions);
+ child = new GGLWidgetInternal(this, shared_context.get());
+ container = QWidget::createWindowContainer(child, this);
- child = new GGLWidgetInternal(fmt, this);
QBoxLayout* layout = new QHBoxLayout(this);
-
- resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height);
- layout->addWidget(child);
+ layout->addWidget(container);
layout->setMargin(0);
setLayout(layout);
+ // Reset minimum size to avoid unwanted resizes when this function is called for a second time.
+ setMinimumSize(1, 1);
+
+ // Show causes the window to actually be created and the OpenGL context as well, but we don't
+ // want the widget to be shown yet, so immediately hide it.
+ show();
+ hide();
+
+ resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height);
+ child->resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height);
+ container->resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height);
+
OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size);
OnFramebufferSizeChanged();
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 3183621bc..9608b959f 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -7,9 +7,9 @@
#include <atomic>
#include <condition_variable>
#include <mutex>
-#include <QGLWidget>
#include <QImage>
#include <QThread>
+#include <QWidget>
#include "common/thread.h"
#include "core/core.h"
#include "core/frontend/emu_window.h"
@@ -21,6 +21,8 @@ class QTouchEvent;
class GGLWidgetInternal;
class GMainWindow;
class GRenderWindow;
+class QSurface;
+class QOpenGLContext;
namespace VideoCore {
enum class LoadCallbackStage;
@@ -121,25 +123,21 @@ public:
void MakeCurrent() override;
void DoneCurrent() override;
void PollEvents() override;
+ std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override;
+
+ void ForwardKeyPressEvent(QKeyEvent* event);
+ void ForwardKeyReleaseEvent(QKeyEvent* event);
void BackupGeometry();
void RestoreGeometry();
void restoreGeometry(const QByteArray& geometry); // overridden
QByteArray saveGeometry(); // overridden
- qreal windowPixelRatio() const;
+ qreal GetWindowPixelRatio() const;
+ std::pair<unsigned, unsigned> ScaleTouch(const QPointF pos) const;
void closeEvent(QCloseEvent* event) override;
-
- void keyPressEvent(QKeyEvent* event) override;
- void keyReleaseEvent(QKeyEvent* event) override;
-
- void mousePressEvent(QMouseEvent* event) override;
- void mouseMoveEvent(QMouseEvent* event) override;
- void mouseReleaseEvent(QMouseEvent* event) override;
-
bool event(QEvent* event) override;
-
void focusOutEvent(QFocusEvent* event) override;
void OnClientAreaResized(unsigned width, unsigned height);
@@ -161,7 +159,6 @@ signals:
void FirstFrameDisplayed();
private:
- std::pair<unsigned, unsigned> ScaleTouch(const QPointF pos) const;
void TouchBeginEvent(const QTouchEvent* event);
void TouchUpdateEvent(const QTouchEvent* event);
void TouchEndEvent();
@@ -169,11 +166,17 @@ private:
void OnMinimalClientAreaChangeRequest(
const std::pair<unsigned, unsigned>& minimal_size) override;
- GGLWidgetInternal* child;
+ QWidget* container = nullptr;
+ GGLWidgetInternal* child = nullptr;
QByteArray geometry;
EmuThread* emu_thread;
+ // Context that backs the GGLWidgetInternal (and will be used by core to render)
+ std::unique_ptr<QOpenGLContext> context;
+ // Context that will be shared between all newly created contexts. This should never be made
+ // current
+ std::unique_ptr<QOpenGLContext> shared_context;
/// Temporary storage of the screenshot taken
QImage screenshot_image;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 802db3945..8725a78dc 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -394,6 +394,7 @@ void Config::ReadValues() {
ReadSetting("use_accurate_gpu_emulation", false).toBool();
Settings::values.use_asynchronous_gpu_emulation =
ReadSetting("use_asynchronous_gpu_emulation", false).toBool();
+ Settings::values.force_30fps_mode = ReadSetting("force_30fps_mode", false).toBool();
Settings::values.bg_red = ReadSetting("bg_red", 0.0).toFloat();
Settings::values.bg_green = ReadSetting("bg_green", 0.0).toFloat();
@@ -523,8 +524,8 @@ void Config::ReadValues() {
qt_config->beginGroup("Paths");
UISettings::values.roms_path = ReadSetting("romsPath").toString();
UISettings::values.symbols_path = ReadSetting("symbolsPath").toString();
- UISettings::values.gamedir = ReadSetting("gameListRootDir", ".").toString();
- UISettings::values.gamedir_deepscan = ReadSetting("gameListDeepScan", false).toBool();
+ UISettings::values.game_directory_path = ReadSetting("gameListRootDir", ".").toString();
+ UISettings::values.game_directory_deepscan = ReadSetting("gameListDeepScan", false).toBool();
UISettings::values.recent_files = ReadSetting("recentFiles").toStringList();
qt_config->endGroup();
@@ -664,6 +665,7 @@ void Config::SaveValues() {
WriteSetting("use_accurate_gpu_emulation", Settings::values.use_accurate_gpu_emulation, false);
WriteSetting("use_asynchronous_gpu_emulation", Settings::values.use_asynchronous_gpu_emulation,
false);
+ WriteSetting("force_30fps_mode", Settings::values.force_30fps_mode, false);
// Cast to double because Qt's written float values are not human-readable
WriteSetting("bg_red", (double)Settings::values.bg_red, 0.0);
@@ -768,8 +770,8 @@ void Config::SaveValues() {
WriteSetting("romsPath", UISettings::values.roms_path);
WriteSetting("symbolsPath", UISettings::values.symbols_path);
WriteSetting("screenshotPath", UISettings::values.screenshot_path);
- WriteSetting("gameListRootDir", UISettings::values.gamedir, ".");
- WriteSetting("gameListDeepScan", UISettings::values.gamedir_deepscan, false);
+ WriteSetting("gameListRootDir", UISettings::values.game_directory_path, ".");
+ WriteSetting("gameListDeepScan", UISettings::values.game_directory_deepscan, false);
WriteSetting("recentFiles", UISettings::values.recent_files);
qt_config->endGroup();
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index eeb038afb..e48f4f5a3 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -28,7 +28,7 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
ConfigureGeneral::~ConfigureGeneral() = default;
void ConfigureGeneral::setConfiguration() {
- ui->toggle_deepscan->setChecked(UISettings::values.gamedir_deepscan);
+ ui->toggle_deepscan->setChecked(UISettings::values.game_directory_deepscan);
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot);
ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
@@ -36,7 +36,7 @@ void ConfigureGeneral::setConfiguration() {
}
void ConfigureGeneral::applyConfiguration() {
- UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked();
+ UISettings::values.game_directory_deepscan = ui->toggle_deepscan->isChecked();
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();
UISettings::values.theme =
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index dd1d67488..0a9883d37 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -77,6 +77,8 @@ void ConfigureGraphics::setConfiguration() {
ui->use_accurate_gpu_emulation->setChecked(Settings::values.use_accurate_gpu_emulation);
ui->use_asynchronous_gpu_emulation->setEnabled(!Core::System::GetInstance().IsPoweredOn());
ui->use_asynchronous_gpu_emulation->setChecked(Settings::values.use_asynchronous_gpu_emulation);
+ ui->force_30fps_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn());
+ ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode);
UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green,
Settings::values.bg_blue));
}
@@ -90,6 +92,7 @@ void ConfigureGraphics::applyConfiguration() {
Settings::values.use_accurate_gpu_emulation = ui->use_accurate_gpu_emulation->isChecked();
Settings::values.use_asynchronous_gpu_emulation =
ui->use_asynchronous_gpu_emulation->isChecked();
+ Settings::values.force_30fps_mode = ui->force_30fps_mode->isChecked();
Settings::values.bg_red = static_cast<float>(bg_color.redF());
Settings::values.bg_green = static_cast<float>(bg_color.greenF());
Settings::values.bg_blue = static_cast<float>(bg_color.blueF());
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui
index c6767e0ca..15ab18ecd 100644
--- a/src/yuzu/configuration/configure_graphics.ui
+++ b/src/yuzu/configuration/configure_graphics.ui
@@ -71,6 +71,13 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="force_30fps_mode">
+ <property name="text">
+ <string>Force 30 FPS mode</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp
deleted file mode 100644
index f2d14becf..000000000
--- a/src/yuzu/debugger/graphics/graphics_surface.cpp
+++ /dev/null
@@ -1,516 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <QBoxLayout>
-#include <QComboBox>
-#include <QDebug>
-#include <QFileDialog>
-#include <QLabel>
-#include <QMessageBox>
-#include <QMouseEvent>
-#include <QPushButton>
-#include <QScrollArea>
-#include <QSpinBox>
-#include "common/vector_math.h"
-#include "core/core.h"
-#include "core/memory.h"
-#include "video_core/engines/maxwell_3d.h"
-#include "video_core/gpu.h"
-#include "video_core/textures/decoders.h"
-#include "video_core/textures/texture.h"
-#include "yuzu/debugger/graphics/graphics_surface.h"
-#include "yuzu/util/spinbox.h"
-
-static Tegra::Texture::TextureFormat ConvertToTextureFormat(
- Tegra::RenderTargetFormat render_target_format) {
- switch (render_target_format) {
- case Tegra::RenderTargetFormat::RGBA8_UNORM:
- return Tegra::Texture::TextureFormat::A8R8G8B8;
- case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
- return Tegra::Texture::TextureFormat::A2B10G10R10;
- default:
- UNIMPLEMENTED_MSG("Unimplemented RT format");
- return Tegra::Texture::TextureFormat::A8R8G8B8;
- }
-}
-
-SurfacePicture::SurfacePicture(QWidget* parent, GraphicsSurfaceWidget* surface_widget_)
- : QLabel(parent), surface_widget(surface_widget_) {}
-
-SurfacePicture::~SurfacePicture() = default;
-
-void SurfacePicture::mousePressEvent(QMouseEvent* event) {
- // Only do something while the left mouse button is held down
- if (!(event->buttons() & Qt::LeftButton))
- return;
-
- if (pixmap() == nullptr)
- return;
-
- if (surface_widget)
- surface_widget->Pick(event->x() * pixmap()->width() / width(),
- event->y() * pixmap()->height() / height());
-}
-
-void SurfacePicture::mouseMoveEvent(QMouseEvent* event) {
- // We also want to handle the event if the user moves the mouse while holding down the LMB
- mousePressEvent(event);
-}
-
-GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Tegra::DebugContext> debug_context,
- QWidget* parent)
- : BreakPointObserverDock(debug_context, tr("Maxwell Surface Viewer"), parent),
- surface_source(Source::RenderTarget0) {
- setObjectName("MaxwellSurface");
-
- surface_source_list = new QComboBox;
- surface_source_list->addItem(tr("Render Target 0"));
- surface_source_list->addItem(tr("Render Target 1"));
- surface_source_list->addItem(tr("Render Target 2"));
- surface_source_list->addItem(tr("Render Target 3"));
- surface_source_list->addItem(tr("Render Target 4"));
- surface_source_list->addItem(tr("Render Target 5"));
- surface_source_list->addItem(tr("Render Target 6"));
- surface_source_list->addItem(tr("Render Target 7"));
- surface_source_list->addItem(tr("Z Buffer"));
- surface_source_list->addItem(tr("Custom"));
- surface_source_list->setCurrentIndex(static_cast<int>(surface_source));
-
- surface_address_control = new CSpinBox;
- surface_address_control->SetBase(16);
- surface_address_control->SetRange(0, 0x7FFFFFFFFFFFFFFF);
- surface_address_control->SetPrefix("0x");
-
- unsigned max_dimension = 16384; // TODO: Find actual maximum
-
- surface_width_control = new QSpinBox;
- surface_width_control->setRange(0, max_dimension);
-
- surface_height_control = new QSpinBox;
- surface_height_control->setRange(0, max_dimension);
-
- surface_picker_x_control = new QSpinBox;
- surface_picker_x_control->setRange(0, max_dimension - 1);
-
- surface_picker_y_control = new QSpinBox;
- surface_picker_y_control->setRange(0, max_dimension - 1);
-
- // clang-format off
- // Color formats sorted by Maxwell texture format index
- const QStringList surface_formats{
- tr("None"),
- QStringLiteral("R32_G32_B32_A32"),
- QStringLiteral("R32_G32_B32"),
- QStringLiteral("R16_G16_B16_A16"),
- QStringLiteral("R32_G32"),
- QStringLiteral("R32_B24G8"),
- QStringLiteral("ETC2_RGB"),
- QStringLiteral("X8B8G8R8"),
- QStringLiteral("A8R8G8B8"),
- QStringLiteral("A2B10G10R10"),
- QStringLiteral("ETC2_RGB_PTA"),
- QStringLiteral("ETC2_RGBA"),
- QStringLiteral("R16_G16"),
- QStringLiteral("G8R24"),
- QStringLiteral("G24R8"),
- QStringLiteral("R32"),
- QStringLiteral("BC6H_SF16"),
- QStringLiteral("BC6H_UF16"),
- QStringLiteral("A4B4G4R4"),
- QStringLiteral("A5B5G5R1"),
- QStringLiteral("A1B5G5R5"),
- QStringLiteral("B5G6R5"),
- QStringLiteral("B6G5R5"),
- QStringLiteral("BC7U"),
- QStringLiteral("G8R8"),
- QStringLiteral("EAC"),
- QStringLiteral("EACX2"),
- QStringLiteral("R16"),
- QStringLiteral("Y8_VIDEO"),
- QStringLiteral("R8"),
- QStringLiteral("G4R4"),
- QStringLiteral("R1"),
- QStringLiteral("E5B9G9R9_SHAREDEXP"),
- QStringLiteral("BF10GF11RF11"),
- QStringLiteral("G8B8G8R8"),
- QStringLiteral("B8G8R8G8"),
- QStringLiteral("DXT1"),
- QStringLiteral("DXT23"),
- QStringLiteral("DXT45"),
- QStringLiteral("DXN1"),
- QStringLiteral("DXN2"),
- QStringLiteral("Z24S8"),
- QStringLiteral("X8Z24"),
- QStringLiteral("S8Z24"),
- QStringLiteral("X4V4Z24__COV4R4V"),
- QStringLiteral("X4V4Z24__COV8R8V"),
- QStringLiteral("V8Z24__COV4R12V"),
- QStringLiteral("ZF32"),
- QStringLiteral("ZF32_X24S8"),
- QStringLiteral("X8Z24_X20V4S8__COV4R4V"),
- QStringLiteral("X8Z24_X20V4S8__COV8R8V"),
- QStringLiteral("ZF32_X20V4X8__COV4R4V"),
- QStringLiteral("ZF32_X20V4X8__COV8R8V"),
- QStringLiteral("ZF32_X20V4S8__COV4R4V"),
- QStringLiteral("ZF32_X20V4S8__COV8R8V"),
- QStringLiteral("X8Z24_X16V8S8__COV4R12V"),
- QStringLiteral("ZF32_X16V8X8__COV4R12V"),
- QStringLiteral("ZF32_X16V8S8__COV4R12V"),
- QStringLiteral("Z16"),
- QStringLiteral("V8Z24__COV8R24V"),
- QStringLiteral("X8Z24_X16V8S8__COV8R24V"),
- QStringLiteral("ZF32_X16V8X8__COV8R24V"),
- QStringLiteral("ZF32_X16V8S8__COV8R24V"),
- QStringLiteral("ASTC_2D_4X4"),
- QStringLiteral("ASTC_2D_5X5"),
- QStringLiteral("ASTC_2D_6X6"),
- QStringLiteral("ASTC_2D_8X8"),
- QStringLiteral("ASTC_2D_10X10"),
- QStringLiteral("ASTC_2D_12X12"),
- QStringLiteral("ASTC_2D_5X4"),
- QStringLiteral("ASTC_2D_6X5"),
- QStringLiteral("ASTC_2D_8X6"),
- QStringLiteral("ASTC_2D_10X8"),
- QStringLiteral("ASTC_2D_12X10"),
- QStringLiteral("ASTC_2D_8X5"),
- QStringLiteral("ASTC_2D_10X5"),
- QStringLiteral("ASTC_2D_10X6"),
- };
- // clang-format on
-
- surface_format_control = new QComboBox;
- surface_format_control->addItems(surface_formats);
-
- surface_info_label = new QLabel();
- surface_info_label->setWordWrap(true);
-
- surface_picture_label = new SurfacePicture(0, this);
- surface_picture_label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
- surface_picture_label->setAlignment(Qt::AlignLeft | Qt::AlignTop);
- surface_picture_label->setScaledContents(false);
-
- auto scroll_area = new QScrollArea();
- scroll_area->setBackgroundRole(QPalette::Dark);
- scroll_area->setWidgetResizable(false);
- scroll_area->setWidget(surface_picture_label);
-
- save_surface = new QPushButton(QIcon::fromTheme("document-save"), tr("Save"));
-
- // Connections
- connect(this, &GraphicsSurfaceWidget::Update, this, &GraphicsSurfaceWidget::OnUpdate);
- connect(surface_source_list, qOverload<int>(&QComboBox::currentIndexChanged), this,
- &GraphicsSurfaceWidget::OnSurfaceSourceChanged);
- connect(surface_address_control, &CSpinBox::ValueChanged, this,
- &GraphicsSurfaceWidget::OnSurfaceAddressChanged);
- connect(surface_width_control, qOverload<int>(&QSpinBox::valueChanged), this,
- &GraphicsSurfaceWidget::OnSurfaceWidthChanged);
- connect(surface_height_control, qOverload<int>(&QSpinBox::valueChanged), this,
- &GraphicsSurfaceWidget::OnSurfaceHeightChanged);
- connect(surface_format_control, qOverload<int>(&QComboBox::currentIndexChanged), this,
- &GraphicsSurfaceWidget::OnSurfaceFormatChanged);
- connect(surface_picker_x_control, qOverload<int>(&QSpinBox::valueChanged), this,
- &GraphicsSurfaceWidget::OnSurfacePickerXChanged);
- connect(surface_picker_y_control, qOverload<int>(&QSpinBox::valueChanged), this,
- &GraphicsSurfaceWidget::OnSurfacePickerYChanged);
- connect(save_surface, &QPushButton::clicked, this, &GraphicsSurfaceWidget::SaveSurface);
-
- auto main_widget = new QWidget;
- auto main_layout = new QVBoxLayout;
- {
- auto sub_layout = new QHBoxLayout;
- sub_layout->addWidget(new QLabel(tr("Source:")));
- sub_layout->addWidget(surface_source_list);
- main_layout->addLayout(sub_layout);
- }
- {
- auto sub_layout = new QHBoxLayout;
- sub_layout->addWidget(new QLabel(tr("GPU Address:")));
- sub_layout->addWidget(surface_address_control);
- main_layout->addLayout(sub_layout);
- }
- {
- auto sub_layout = new QHBoxLayout;
- sub_layout->addWidget(new QLabel(tr("Width:")));
- sub_layout->addWidget(surface_width_control);
- main_layout->addLayout(sub_layout);
- }
- {
- auto sub_layout = new QHBoxLayout;
- sub_layout->addWidget(new QLabel(tr("Height:")));
- sub_layout->addWidget(surface_height_control);
- main_layout->addLayout(sub_layout);
- }
- {
- auto sub_layout = new QHBoxLayout;
- sub_layout->addWidget(new QLabel(tr("Format:")));
- sub_layout->addWidget(surface_format_control);
- main_layout->addLayout(sub_layout);
- }
- main_layout->addWidget(scroll_area);
-
- auto info_layout = new QHBoxLayout;
- {
- auto xy_layout = new QVBoxLayout;
- {
- {
- auto sub_layout = new QHBoxLayout;
- sub_layout->addWidget(new QLabel(tr("X:")));
- sub_layout->addWidget(surface_picker_x_control);
- xy_layout->addLayout(sub_layout);
- }
- {
- auto sub_layout = new QHBoxLayout;
- sub_layout->addWidget(new QLabel(tr("Y:")));
- sub_layout->addWidget(surface_picker_y_control);
- xy_layout->addLayout(sub_layout);
- }
- }
- info_layout->addLayout(xy_layout);
- surface_info_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
- info_layout->addWidget(surface_info_label);
- }
- main_layout->addLayout(info_layout);
-
- main_layout->addWidget(save_surface);
- main_widget->setLayout(main_layout);
- setWidget(main_widget);
-
- // Load current data - TODO: Make sure this works when emulation is not running
- if (debug_context && debug_context->at_breakpoint) {
- emit Update();
- widget()->setEnabled(debug_context->at_breakpoint);
- } else {
- widget()->setEnabled(false);
- }
-}
-
-void GraphicsSurfaceWidget::OnBreakPointHit(Tegra::DebugContext::Event event, void* data) {
- emit Update();
- widget()->setEnabled(true);
-}
-
-void GraphicsSurfaceWidget::OnResumed() {
- widget()->setEnabled(false);
-}
-
-void GraphicsSurfaceWidget::OnSurfaceSourceChanged(int new_value) {
- surface_source = static_cast<Source>(new_value);
- emit Update();
-}
-
-void GraphicsSurfaceWidget::OnSurfaceAddressChanged(qint64 new_value) {
- if (surface_address != new_value) {
- surface_address = static_cast<GPUVAddr>(new_value);
-
- surface_source_list->setCurrentIndex(static_cast<int>(Source::Custom));
- emit Update();
- }
-}
-
-void GraphicsSurfaceWidget::OnSurfaceWidthChanged(int new_value) {
- if (surface_width != static_cast<unsigned>(new_value)) {
- surface_width = static_cast<unsigned>(new_value);
-
- surface_source_list->setCurrentIndex(static_cast<int>(Source::Custom));
- emit Update();
- }
-}
-
-void GraphicsSurfaceWidget::OnSurfaceHeightChanged(int new_value) {
- if (surface_height != static_cast<unsigned>(new_value)) {
- surface_height = static_cast<unsigned>(new_value);
-
- surface_source_list->setCurrentIndex(static_cast<int>(Source::Custom));
- emit Update();
- }
-}
-
-void GraphicsSurfaceWidget::OnSurfaceFormatChanged(int new_value) {
- if (surface_format != static_cast<Tegra::Texture::TextureFormat>(new_value)) {
- surface_format = static_cast<Tegra::Texture::TextureFormat>(new_value);
-
- surface_source_list->setCurrentIndex(static_cast<int>(Source::Custom));
- emit Update();
- }
-}
-
-void GraphicsSurfaceWidget::OnSurfacePickerXChanged(int new_value) {
- if (surface_picker_x != new_value) {
- surface_picker_x = new_value;
- Pick(surface_picker_x, surface_picker_y);
- }
-}
-
-void GraphicsSurfaceWidget::OnSurfacePickerYChanged(int new_value) {
- if (surface_picker_y != new_value) {
- surface_picker_y = new_value;
- Pick(surface_picker_x, surface_picker_y);
- }
-}
-
-void GraphicsSurfaceWidget::Pick(int x, int y) {
- surface_picker_x_control->setValue(x);
- surface_picker_y_control->setValue(y);
-
- if (x < 0 || x >= static_cast<int>(surface_width) || y < 0 ||
- y >= static_cast<int>(surface_height)) {
- surface_info_label->setText(tr("Pixel out of bounds"));
- surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
- return;
- }
-
- surface_info_label->setText(QString("Raw: <Unimplemented>\n(%1)").arg("<Unimplemented>"));
- surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
-}
-
-void GraphicsSurfaceWidget::OnUpdate() {
- auto& gpu = Core::System::GetInstance().GPU();
-
- QPixmap pixmap;
-
- switch (surface_source) {
- case Source::RenderTarget0:
- case Source::RenderTarget1:
- case Source::RenderTarget2:
- case Source::RenderTarget3:
- case Source::RenderTarget4:
- case Source::RenderTarget5:
- case Source::RenderTarget6:
- case Source::RenderTarget7: {
- // TODO: Store a reference to the registers in the debug context instead of accessing them
- // directly...
-
- const auto& registers = gpu.Maxwell3D().regs;
- const auto& rt = registers.rt[static_cast<std::size_t>(surface_source) -
- static_cast<std::size_t>(Source::RenderTarget0)];
-
- surface_address = rt.Address();
- surface_width = rt.width;
- surface_height = rt.height;
- if (rt.format != Tegra::RenderTargetFormat::NONE) {
- surface_format = ConvertToTextureFormat(rt.format);
- }
-
- break;
- }
-
- case Source::Custom: {
- // Keep user-specified values
- break;
- }
-
- default:
- qDebug() << "Unknown surface source " << static_cast<int>(surface_source);
- break;
- }
-
- surface_address_control->SetValue(surface_address);
- surface_width_control->setValue(surface_width);
- surface_height_control->setValue(surface_height);
- surface_format_control->setCurrentIndex(static_cast<int>(surface_format));
-
- if (surface_address == 0) {
- surface_picture_label->hide();
- surface_info_label->setText(tr("(invalid surface address)"));
- surface_info_label->setAlignment(Qt::AlignCenter);
- surface_picker_x_control->setEnabled(false);
- surface_picker_y_control->setEnabled(false);
- save_surface->setEnabled(false);
- return;
- }
-
- // TODO: Implement a good way to visualize alpha components!
-
- QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32);
-
- // TODO(bunnei): Will not work with BCn formats that swizzle 4x4 tiles.
- // Needs to be fixed if we plan to use this feature more, otherwise we may remove it.
- auto unswizzled_data = Tegra::Texture::UnswizzleTexture(
- gpu.MemoryManager().GetPointer(surface_address), 1, 1,
- Tegra::Texture::BytesPerPixel(surface_format), surface_width, surface_height, 1U);
-
- auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format,
- surface_width, surface_height);
-
- surface_picture_label->show();
-
- for (unsigned int y = 0; y < surface_height; ++y) {
- for (unsigned int x = 0; x < surface_width; ++x) {
- Common::Vec4<u8> color;
- color[0] = texture_data[x + y * surface_width + 0];
- color[1] = texture_data[x + y * surface_width + 1];
- color[2] = texture_data[x + y * surface_width + 2];
- color[3] = texture_data[x + y * surface_width + 3];
- decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), color.a()));
- }
- }
-
- pixmap = QPixmap::fromImage(decoded_image);
- surface_picture_label->setPixmap(pixmap);
- surface_picture_label->resize(pixmap.size());
-
- // Update the info with pixel data
- surface_picker_x_control->setEnabled(true);
- surface_picker_y_control->setEnabled(true);
- Pick(surface_picker_x, surface_picker_y);
-
- // Enable saving the converted pixmap to file
- save_surface->setEnabled(true);
-}
-
-void GraphicsSurfaceWidget::SaveSurface() {
- const QString png_filter = tr("Portable Network Graphic (*.png)");
- const QString bin_filter = tr("Binary data (*.bin)");
-
- QString selected_filter;
- const QString filename = QFileDialog::getSaveFileName(
- this, tr("Save Surface"),
- QStringLiteral("texture-0x%1.png").arg(QString::number(surface_address, 16)),
- QStringLiteral("%1;;%2").arg(png_filter, bin_filter), &selected_filter);
-
- if (filename.isEmpty()) {
- // If the user canceled the dialog, don't save anything.
- return;
- }
-
- if (selected_filter == png_filter) {
- const QPixmap* const pixmap = surface_picture_label->pixmap();
- ASSERT_MSG(pixmap != nullptr, "No pixmap set");
-
- QFile file{filename};
- if (!file.open(QIODevice::WriteOnly)) {
- QMessageBox::warning(this, tr("Error"), tr("Failed to open file '%1'").arg(filename));
- return;
- }
-
- if (!pixmap->save(&file, "PNG")) {
- QMessageBox::warning(this, tr("Error"),
- tr("Failed to save surface data to file '%1'").arg(filename));
- }
- } else if (selected_filter == bin_filter) {
- auto& gpu = Core::System::GetInstance().GPU();
- const std::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address);
-
- const u8* const buffer = Memory::GetPointer(*address);
- ASSERT_MSG(buffer != nullptr, "Memory not accessible");
-
- QFile file{filename};
- if (!file.open(QIODevice::WriteOnly)) {
- QMessageBox::warning(this, tr("Error"), tr("Failed to open file '%1'").arg(filename));
- return;
- }
-
- const int size =
- surface_width * surface_height * Tegra::Texture::BytesPerPixel(surface_format);
- const QByteArray data(reinterpret_cast<const char*>(buffer), size);
- if (file.write(data) != data.size()) {
- QMessageBox::warning(
- this, tr("Error"),
- tr("Failed to completely write surface data to file. The saved data will "
- "likely be corrupt."));
- }
- } else {
- UNREACHABLE_MSG("Unhandled filter selected");
- }
-}
diff --git a/src/yuzu/debugger/graphics/graphics_surface.h b/src/yuzu/debugger/graphics/graphics_surface.h
deleted file mode 100644
index 89445b18f..000000000
--- a/src/yuzu/debugger/graphics/graphics_surface.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <QLabel>
-#include <QPushButton>
-#include "video_core/memory_manager.h"
-#include "video_core/textures/texture.h"
-#include "yuzu/debugger/graphics/graphics_breakpoint_observer.h"
-
-class QComboBox;
-class QSpinBox;
-class CSpinBox;
-
-class GraphicsSurfaceWidget;
-
-class SurfacePicture : public QLabel {
- Q_OBJECT
-
-public:
- explicit SurfacePicture(QWidget* parent = nullptr,
- GraphicsSurfaceWidget* surface_widget = nullptr);
- ~SurfacePicture() override;
-
-protected slots:
- void mouseMoveEvent(QMouseEvent* event) override;
- void mousePressEvent(QMouseEvent* event) override;
-
-private:
- GraphicsSurfaceWidget* surface_widget;
-};
-
-class GraphicsSurfaceWidget : public BreakPointObserverDock {
- Q_OBJECT
-
- using Event = Tegra::DebugContext::Event;
-
- enum class Source {
- RenderTarget0 = 0,
- RenderTarget1 = 1,
- RenderTarget2 = 2,
- RenderTarget3 = 3,
- RenderTarget4 = 4,
- RenderTarget5 = 5,
- RenderTarget6 = 6,
- RenderTarget7 = 7,
- ZBuffer = 8,
- Custom = 9,
- };
-
-public:
- explicit GraphicsSurfaceWidget(std::shared_ptr<Tegra::DebugContext> debug_context,
- QWidget* parent = nullptr);
- void Pick(int x, int y);
-
-public slots:
- void OnSurfaceSourceChanged(int new_value);
- void OnSurfaceAddressChanged(qint64 new_value);
- void OnSurfaceWidthChanged(int new_value);
- void OnSurfaceHeightChanged(int new_value);
- void OnSurfaceFormatChanged(int new_value);
- void OnSurfacePickerXChanged(int new_value);
- void OnSurfacePickerYChanged(int new_value);
- void OnUpdate();
-
-signals:
- void Update();
-
-private:
- void OnBreakPointHit(Tegra::DebugContext::Event event, void* data) override;
- void OnResumed() override;
-
- void SaveSurface();
-
- QComboBox* surface_source_list;
- CSpinBox* surface_address_control;
- QSpinBox* surface_width_control;
- QSpinBox* surface_height_control;
- QComboBox* surface_format_control;
-
- SurfacePicture* surface_picture_label;
- QSpinBox* surface_picker_x_control;
- QSpinBox* surface_picker_y_control;
- QLabel* surface_info_label;
- QPushButton* save_surface;
-
- Source surface_source;
- GPUVAddr surface_address;
- unsigned surface_width;
- unsigned surface_height;
- Tegra::Texture::TextureFormat surface_format;
- int surface_picker_x = 0;
- int surface_picker_y = 0;
-};
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 4b67656ac..b0ca766ec 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -467,9 +467,10 @@ void GameList::LoadInterfaceLayout() {
const QStringList GameList::supported_file_extensions = {"nso", "nro", "nca", "xci", "nsp"};
void GameList::RefreshGameDirectory() {
- if (!UISettings::values.gamedir.isEmpty() && current_worker != nullptr) {
+ if (!UISettings::values.game_directory_path.isEmpty() && current_worker != nullptr) {
LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list.");
search_field->clear();
- PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
+ PopulateAsync(UISettings::values.game_directory_path,
+ UISettings::values.game_directory_deepscan);
}
}
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index d5a328d92..bdee44b04 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -90,7 +90,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "yuzu/configuration/configure_dialog.h"
#include "yuzu/debugger/console.h"
#include "yuzu/debugger/graphics/graphics_breakpoints.h"
-#include "yuzu/debugger/graphics/graphics_surface.h"
#include "yuzu/debugger/profiler.h"
#include "yuzu/debugger/wait_tree.h"
#include "yuzu/discord.h"
@@ -214,7 +213,8 @@ GMainWindow::GMainWindow()
OnReinitializeKeys(ReinitializeKeyBehavior::NoWarning);
game_list->LoadCompatibilityList();
- game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
+ game_list->PopulateAsync(UISettings::values.game_directory_path,
+ UISettings::values.game_directory_deepscan);
// Show one-time "callout" messages to the user
ShowTelemetryCallout();
@@ -483,11 +483,6 @@ void GMainWindow::InitializeDebugWidgets() {
graphicsBreakpointsWidget->hide();
debug_menu->addAction(graphicsBreakpointsWidget->toggleViewAction());
- graphicsSurfaceWidget = new GraphicsSurfaceWidget(debug_context, this);
- addDockWidget(Qt::RightDockWidgetArea, graphicsSurfaceWidget);
- graphicsSurfaceWidget->hide();
- debug_menu->addAction(graphicsSurfaceWidget->toggleViewAction());
-
waitTreeWidget = new WaitTreeWidget(this);
addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget);
waitTreeWidget->hide();
@@ -1284,8 +1279,8 @@ void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) {
const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false);
if (reload) {
- game_list->PopulateAsync(UISettings::values.gamedir,
- UISettings::values.gamedir_deepscan);
+ game_list->PopulateAsync(UISettings::values.game_directory_path,
+ UISettings::values.game_directory_deepscan);
}
config->Save();
@@ -1373,7 +1368,8 @@ void GMainWindow::OnMenuInstallToNAND() {
const auto success = [this]() {
QMessageBox::information(this, tr("Successfully Installed"),
tr("The file was successfully installed."));
- game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
+ game_list->PopulateAsync(UISettings::values.game_directory_path,
+ UISettings::values.game_directory_deepscan);
};
const auto failed = [this]() {
@@ -1500,8 +1496,8 @@ void GMainWindow::OnMenuInstallToNAND() {
void GMainWindow::OnMenuSelectGameListRoot() {
QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
if (!dir_path.isEmpty()) {
- UISettings::values.gamedir = dir_path;
- game_list->PopulateAsync(dir_path, UISettings::values.gamedir_deepscan);
+ UISettings::values.game_directory_path = dir_path;
+ game_list->PopulateAsync(dir_path, UISettings::values.game_directory_deepscan);
}
}
@@ -1523,7 +1519,8 @@ void GMainWindow::OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget target)
: FileUtil::UserPath::NANDDir,
dir_path.toStdString());
Service::FileSystem::CreateFactories(*vfs);
- game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
+ game_list->PopulateAsync(UISettings::values.game_directory_path,
+ UISettings::values.game_directory_deepscan);
}
}
@@ -1675,8 +1672,8 @@ void GMainWindow::OnConfigure() {
const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false);
if (reload) {
- game_list->PopulateAsync(UISettings::values.gamedir,
- UISettings::values.gamedir_deepscan);
+ game_list->PopulateAsync(UISettings::values.game_directory_path,
+ UISettings::values.game_directory_deepscan);
}
config->Save();
@@ -1926,7 +1923,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
Service::FileSystem::CreateFactories(*vfs);
if (behavior == ReinitializeKeyBehavior::Warning) {
- game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
+ game_list->PopulateAsync(UISettings::values.game_directory_path,
+ UISettings::values.game_directory_deepscan);
}
}
@@ -2033,6 +2031,18 @@ void GMainWindow::dragMoveEvent(QDragMoveEvent* event) {
event->acceptProposedAction();
}
+void GMainWindow::keyPressEvent(QKeyEvent* event) {
+ if (render_window) {
+ render_window->ForwardKeyPressEvent(event);
+ }
+}
+
+void GMainWindow::keyReleaseEvent(QKeyEvent* event) {
+ if (render_window) {
+ render_window->ForwardKeyReleaseEvent(event);
+ }
+}
+
bool GMainWindow::ConfirmChangeGame() {
if (emu_thread == nullptr)
return true;
@@ -2100,7 +2110,8 @@ int main(int argc, char* argv[]) {
QCoreApplication::setOrganizationName("yuzu team");
QCoreApplication::setApplicationName("yuzu");
- QApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);
+ // Enables the core to make the qt created contexts current on std::threads
+ QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);
QApplication app(argc, argv);
// Qt changes the locale and causes issues in float conversion using std::to_string() when
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index c727e942c..ce5045819 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -23,7 +23,6 @@ class EmuThread;
class GameList;
class GImageInfo;
class GraphicsBreakPointsWidget;
-class GraphicsSurfaceWidget;
class GRenderWindow;
class LoadingScreen;
class MicroProfileDialog;
@@ -240,7 +239,6 @@ private:
ProfilerWidget* profilerWidget;
MicroProfileDialog* microProfileDialog;
GraphicsBreakPointsWidget* graphicsBreakpointsWidget;
- GraphicsSurfaceWidget* graphicsSurfaceWidget;
WaitTreeWidget* waitTreeWidget;
QAction* actions_recent_files[max_recent_files_item];
@@ -254,4 +252,8 @@ protected:
void dropEvent(QDropEvent* event) override;
void dragEnterEvent(QDragEnterEvent* event) override;
void dragMoveEvent(QDragMoveEvent* event) override;
+
+ // Overrides used to forward signals to the render window when the focus moves out.
+ void keyPressEvent(QKeyEvent* event) override;
+ void keyReleaseEvent(QKeyEvent* event) override;
};
diff --git a/src/yuzu/ui_settings.h b/src/yuzu/ui_settings.h
index 45e705b61..dbd318e20 100644
--- a/src/yuzu/ui_settings.h
+++ b/src/yuzu/ui_settings.h
@@ -55,8 +55,8 @@ struct Values {
QString roms_path;
QString symbols_path;
QString screenshot_path;
- QString gamedir;
- bool gamedir_deepscan;
+ QString game_directory_path;
+ bool game_directory_deepscan;
QStringList recent_files;
QString theme;