Compare commits

...

8 Commits

Author SHA1 Message Date
4505760ec7 renderer_gl: Disable stereo on bottom screen 2023-08-07 17:16:01 +03:00
651663e5f7 renderer_gl: Add swap eyes options
* Remove reverse interlaced in favour of the checkbox
2023-08-07 03:27:30 +03:00
a9e5e59d9a core: frontend: Add top-bottom stereo rendering option 2023-08-07 03:27:23 +03:00
96c375229b host_shaders: Improve anaglyph quality
* Use matrices optimized for LCD displays
2023-08-07 03:27:17 +03:00
ea928374a6 renderer_opengl: Adjust interlaced lines to monitor 2023-08-07 03:27:11 +03:00
20f4677f80 qt: Fix dark themes not showing alternating row icons with Qt 6.5.2 (#6862) 2023-08-06 12:24:03 -07:00
0048e61fc7 Fix compilation without ENABLE_WEB_SERVICE (#6856) 2023-08-06 12:23:53 -07:00
aaeba6759e citra_qt: do not pass memory to widget (#6849) 2023-08-04 16:35:52 -07:00
34 changed files with 295 additions and 184 deletions

View File

@ -57,6 +57,7 @@ CMAKE_DEPENDENT_OPTION(ENABLE_TESTS "Enable generating tests executable" ON "NOT
CMAKE_DEPENDENT_OPTION(ENABLE_DEDICATED_ROOM "Enable generating dedicated room executable" ON "NOT ANDROID AND NOT IOS" OFF) CMAKE_DEPENDENT_OPTION(ENABLE_DEDICATED_ROOM "Enable generating dedicated room executable" ON "NOT ANDROID AND NOT IOS" OFF)
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
option(ENABLE_SCRIPTING "Enable RPC server for scripting" ON)
CMAKE_DEPENDENT_OPTION(ENABLE_CUBEB "Enables the cubeb audio backend" ON "NOT IOS" OFF) CMAKE_DEPENDENT_OPTION(ENABLE_CUBEB "Enables the cubeb audio backend" ON "NOT IOS" OFF)
option(ENABLE_OPENAL "Enables the OpenAL audio backend" ON) option(ENABLE_OPENAL "Enables the OpenAL audio backend" ON)

View File

@ -298,6 +298,11 @@ QAbstractItemView:read-only {
alternate-background-color: #232629; alternate-background-color: #232629;
} }
/* Workaround for https://bugreports.qt.io/browse/QTBUG-115529 */
QAbstractItemView:item {
border: 0px;
}
QWidget:focus { QWidget:focus {
border: 1px solid #3daee9; border: 1px solid #3daee9;
} }

View File

@ -481,6 +481,11 @@ QAbstractItemView QLineEdit {
padding: 2px; padding: 2px;
} }
/* Workaround for https://bugreports.qt.io/browse/QTBUG-115529 */
QAbstractItemView:item {
border: 0px;
}
/* QAbstractScrollArea ---------------------------------------------------- /* QAbstractScrollArea ----------------------------------------------------
https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qabstractscrollarea

View File

@ -173,15 +173,15 @@ endif()
add_library(json-headers INTERFACE) add_library(json-headers INTERFACE)
target_include_directories(json-headers INTERFACE ./json) target_include_directories(json-headers INTERFACE ./json)
if (ENABLE_WEB_SERVICE) # OpenSSL
if (USE_SYSTEM_OPENSSL) if (USE_SYSTEM_OPENSSL)
find_package(OpenSSL 1.1) find_package(OpenSSL 1.1)
if (OPENSSL_FOUND) if (OPENSSL_FOUND)
set(OPENSSL_LIBRARIES OpenSSL::SSL OpenSSL::Crypto) set(OPENSSL_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)
endif() endif()
endif() endif()
if (NOT OPENSSL_FOUND) if (NOT OPENSSL_FOUND)
# LibreSSL # LibreSSL
set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "") set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "")
set(OPENSSLDIR "/etc/ssl/") set(OPENSSLDIR "/etc/ssl/")
@ -191,19 +191,20 @@ if (ENABLE_WEB_SERVICE)
get_directory_property(OPENSSL_LIBRARIES get_directory_property(OPENSSL_LIBRARIES
DIRECTORY libressl DIRECTORY libressl
DEFINITION OPENSSL_LIBS) DEFINITION OPENSSL_LIBS)
endif() endif()
if(ANDROID) # httplib
add_library(httplib INTERFACE)
target_include_directories(httplib INTERFACE ./httplib)
target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
if(ANDROID)
add_subdirectory(android-ifaddrs) add_subdirectory(android-ifaddrs)
endif() endif()
# httplib # cpp-jwt
add_library(httplib INTERFACE) if (ENABLE_WEB_SERVICE)
target_include_directories(httplib INTERFACE ./httplib)
target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
# cpp-jwt
add_library(cpp-jwt INTERFACE) add_library(cpp-jwt INTERFACE)
target_include_directories(cpp-jwt INTERFACE ./cpp-jwt/include) target_include_directories(cpp-jwt INTERFACE ./cpp-jwt/include)
target_compile_definitions(cpp-jwt INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON) target_compile_definitions(cpp-jwt INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON)

View File

@ -143,7 +143,7 @@ void Config::ReadValues() {
ReadSetting("Renderer", Settings::values.use_vsync_new); ReadSetting("Renderer", Settings::values.use_vsync_new);
ReadSetting("Renderer", Settings::values.texture_filter); ReadSetting("Renderer", Settings::values.texture_filter);
ReadSetting("Renderer", Settings::values.mono_render_option); ReadSetting("Renderer", Settings::values.swap_eyes);
ReadSetting("Renderer", Settings::values.render_3d); ReadSetting("Renderer", Settings::values.render_3d);
ReadSetting("Renderer", Settings::values.factor_3d); ReadSetting("Renderer", Settings::values.factor_3d);
ReadSetting("Renderer", Settings::values.pp_shader_name); ReadSetting("Renderer", Settings::values.pp_shader_name);

View File

@ -582,6 +582,14 @@ void GRenderWindow::resizeEvent(QResizeEvent* event) {
OnFramebufferSizeChanged(); OnFramebufferSizeChanged();
} }
void GRenderWindow::moveEvent(QMoveEvent* event) {
QWidget::moveEvent(event);
if (is_secondary) {
const auto screen_pos = Common::MakeVec(pos().x(), pos().y());
SetScreenPos(screen_pos);
}
}
bool GRenderWindow::InitRenderTarget() { bool GRenderWindow::InitRenderTarget() {
{ {
// Create a dummy render widget so that Qt // Create a dummy render widget so that Qt

View File

@ -136,6 +136,7 @@ public:
void closeEvent(QCloseEvent* event) override; void closeEvent(QCloseEvent* event) override;
void resizeEvent(QResizeEvent* event) override; void resizeEvent(QResizeEvent* event) override;
void moveEvent(QMoveEvent* event) override;
void keyPressEvent(QKeyEvent* event) override; void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override;

View File

@ -505,9 +505,9 @@ void Config::ReadLayoutValues() {
ReadGlobalSetting(Settings::values.swap_screen); ReadGlobalSetting(Settings::values.swap_screen);
ReadGlobalSetting(Settings::values.upright_screen); ReadGlobalSetting(Settings::values.upright_screen);
ReadGlobalSetting(Settings::values.large_screen_proportion); ReadGlobalSetting(Settings::values.large_screen_proportion);
ReadBasicSetting(Settings::values.swap_eyes);
if (global) { if (global) {
ReadBasicSetting(Settings::values.mono_render_option);
ReadBasicSetting(Settings::values.custom_layout); ReadBasicSetting(Settings::values.custom_layout);
ReadBasicSetting(Settings::values.custom_top_left); ReadBasicSetting(Settings::values.custom_top_left);
ReadBasicSetting(Settings::values.custom_top_top); ReadBasicSetting(Settings::values.custom_top_top);
@ -1017,9 +1017,9 @@ void Config::SaveLayoutValues() {
WriteGlobalSetting(Settings::values.swap_screen); WriteGlobalSetting(Settings::values.swap_screen);
WriteGlobalSetting(Settings::values.upright_screen); WriteGlobalSetting(Settings::values.upright_screen);
WriteGlobalSetting(Settings::values.large_screen_proportion); WriteGlobalSetting(Settings::values.large_screen_proportion);
WriteBasicSetting(Settings::values.swap_eyes);
if (global) { if (global) {
WriteBasicSetting(Settings::values.mono_render_option);
WriteBasicSetting(Settings::values.custom_layout); WriteBasicSetting(Settings::values.custom_layout);
WriteBasicSetting(Settings::values.custom_top_left); WriteBasicSetting(Settings::values.custom_top_left);
WriteBasicSetting(Settings::values.custom_top_top); WriteBasicSetting(Settings::values.custom_top_top);

View File

@ -74,9 +74,8 @@ void ConfigureEnhancements::SetConfiguration() {
ui->render_3d_combobox->setCurrentIndex( ui->render_3d_combobox->setCurrentIndex(
static_cast<int>(Settings::values.render_3d.GetValue())); static_cast<int>(Settings::values.render_3d.GetValue()));
ui->factor_3d->setValue(Settings::values.factor_3d.GetValue()); ui->factor_3d->setValue(Settings::values.factor_3d.GetValue());
ui->mono_rendering_eye->setCurrentIndex(
static_cast<int>(Settings::values.mono_render_option.GetValue()));
updateShaders(Settings::values.render_3d.GetValue()); updateShaders(Settings::values.render_3d.GetValue());
ui->toggle_swap_eyes->setChecked(Settings::values.swap_eyes.GetValue());
ui->toggle_linear_filter->setChecked(Settings::values.filter_mode.GetValue()); ui->toggle_linear_filter->setChecked(Settings::values.filter_mode.GetValue());
ui->toggle_swap_screen->setChecked(Settings::values.swap_screen.GetValue()); ui->toggle_swap_screen->setChecked(Settings::values.swap_screen.GetValue());
ui->toggle_upright_screen->setChecked(Settings::values.upright_screen.GetValue()); ui->toggle_upright_screen->setChecked(Settings::values.upright_screen.GetValue());
@ -98,8 +97,7 @@ void ConfigureEnhancements::updateShaders(Settings::StereoRenderOption stereo_op
ui->shader_combobox->clear(); ui->shader_combobox->clear();
ui->shader_combobox->setEnabled(true); ui->shader_combobox->setEnabled(true);
if (stereo_option == Settings::StereoRenderOption::Interlaced || if (stereo_option == Settings::StereoRenderOption::Interlaced) {
stereo_option == Settings::StereoRenderOption::ReverseInterlaced) {
ui->shader_combobox->addItem(QStringLiteral("horizontal (builtin)")); ui->shader_combobox->addItem(QStringLiteral("horizontal (builtin)"));
ui->shader_combobox->setCurrentIndex(0); ui->shader_combobox->setCurrentIndex(0);
ui->shader_combobox->setEnabled(false); ui->shader_combobox->setEnabled(false);
@ -135,8 +133,6 @@ void ConfigureEnhancements::ApplyConfiguration() {
Settings::values.render_3d = Settings::values.render_3d =
static_cast<Settings::StereoRenderOption>(ui->render_3d_combobox->currentIndex()); static_cast<Settings::StereoRenderOption>(ui->render_3d_combobox->currentIndex());
Settings::values.factor_3d = ui->factor_3d->value(); Settings::values.factor_3d = ui->factor_3d->value();
Settings::values.mono_render_option =
static_cast<Settings::MonoRenderOption>(ui->mono_rendering_eye->currentIndex());
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph) { if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph) {
Settings::values.anaglyph_shader_name = Settings::values.anaglyph_shader_name =
ui->shader_combobox->itemText(ui->shader_combobox->currentIndex()).toStdString(); ui->shader_combobox->itemText(ui->shader_combobox->currentIndex()).toStdString();
@ -146,6 +142,8 @@ void ConfigureEnhancements::ApplyConfiguration() {
} }
Settings::values.large_screen_proportion = ui->large_screen_proportion->value(); Settings::values.large_screen_proportion = ui->large_screen_proportion->value();
ConfigurationShared::ApplyPerGameSetting(&Settings::values.swap_eyes, ui->toggle_swap_eyes,
swap_eyes);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.filter_mode, ConfigurationShared::ApplyPerGameSetting(&Settings::values.filter_mode,
ui->toggle_linear_filter, linear_filter); ui->toggle_linear_filter, linear_filter);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.texture_filter, ConfigurationShared::ApplyPerGameSetting(&Settings::values.texture_filter,
@ -174,6 +172,7 @@ void ConfigureEnhancements::SetupPerGameUI() {
if (Settings::IsConfiguringGlobal()) { if (Settings::IsConfiguringGlobal()) {
ui->widget_resolution->setEnabled(Settings::values.resolution_factor.UsingGlobal()); ui->widget_resolution->setEnabled(Settings::values.resolution_factor.UsingGlobal());
ui->widget_texture_filter->setEnabled(Settings::values.texture_filter.UsingGlobal()); ui->widget_texture_filter->setEnabled(Settings::values.texture_filter.UsingGlobal());
ui->toggle_swap_eyes->setEnabled(Settings::values.swap_eyes.UsingGlobal());
ui->toggle_linear_filter->setEnabled(Settings::values.filter_mode.UsingGlobal()); ui->toggle_linear_filter->setEnabled(Settings::values.filter_mode.UsingGlobal());
ui->toggle_swap_screen->setEnabled(Settings::values.swap_screen.UsingGlobal()); ui->toggle_swap_screen->setEnabled(Settings::values.swap_screen.UsingGlobal());
ui->toggle_upright_screen->setEnabled(Settings::values.upright_screen.UsingGlobal()); ui->toggle_upright_screen->setEnabled(Settings::values.upright_screen.UsingGlobal());
@ -193,6 +192,8 @@ void ConfigureEnhancements::SetupPerGameUI() {
linear_filter); linear_filter);
ConfigurationShared::SetColoredTristate(ui->toggle_swap_screen, Settings::values.swap_screen, ConfigurationShared::SetColoredTristate(ui->toggle_swap_screen, Settings::values.swap_screen,
swap_screen); swap_screen);
ConfigurationShared::SetColoredTristate(ui->toggle_swap_eyes, Settings::values.swap_eyes,
swap_eyes);
ConfigurationShared::SetColoredTristate(ui->toggle_upright_screen, ConfigurationShared::SetColoredTristate(ui->toggle_upright_screen,
Settings::values.upright_screen, upright_screen); Settings::values.upright_screen, upright_screen);
ConfigurationShared::SetColoredTristate(ui->toggle_dump_textures, ConfigurationShared::SetColoredTristate(ui->toggle_dump_textures,

View File

@ -45,5 +45,6 @@ private:
ConfigurationShared::CheckState custom_textures; ConfigurationShared::CheckState custom_textures;
ConfigurationShared::CheckState preload_textures; ConfigurationShared::CheckState preload_textures;
ConfigurationShared::CheckState async_custom_loading; ConfigurationShared::CheckState async_custom_loading;
ConfigurationShared::CheckState swap_eyes;
QColor bg_color; QColor bg_color;
}; };

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>440</width> <width>440</width>
<height>748</height> <height>781</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
@ -239,6 +239,11 @@
<string>Side by Side</string> <string>Side by Side</string>
</property> </property>
</item> </item>
<item>
<property name="text">
<string>Top Bottom</string>
</property>
</item>
<item> <item>
<property name="text"> <property name="text">
<string>Anaglyph</string> <string>Anaglyph</string>
@ -249,11 +254,6 @@
<string>Interlaced</string> <string>Interlaced</string>
</property> </property>
</item> </item>
<item>
<property name="text">
<string>Reverse Interlaced</string>
</property>
</item>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -288,26 +288,12 @@
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_9"> <layout class="QHBoxLayout" name="horizontalLayout_9">
<item> <item>
<widget class="QLabel" name="label_6"> <widget class="QCheckBox" name="toggle_swap_eyes">
<property name="text"> <property name="text">
<string>Eye to Render in Monoscopic Mode</string> <string>Swap Eyes</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QComboBox" name="mono_rendering_eye">
<item>
<property name="text">
<string>Left Eye (default)</string>
</property>
</item>
<item>
<property name="text">
<string>Right Eye</string>
</property>
</item>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>
@ -539,7 +525,6 @@
<tabstop>texture_filter_combobox</tabstop> <tabstop>texture_filter_combobox</tabstop>
<tabstop>render_3d_combobox</tabstop> <tabstop>render_3d_combobox</tabstop>
<tabstop>factor_3d</tabstop> <tabstop>factor_3d</tabstop>
<tabstop>mono_rendering_eye</tabstop>
<tabstop>layout_combobox</tabstop> <tabstop>layout_combobox</tabstop>
<tabstop>toggle_swap_screen</tabstop> <tabstop>toggle_swap_screen</tabstop>
<tabstop>toggle_upright_screen</tabstop> <tabstop>toggle_upright_screen</tabstop>

View File

@ -16,6 +16,7 @@
#include "citra_qt/debugger/graphics/graphics_cmdlists.h" #include "citra_qt/debugger/graphics/graphics_cmdlists.h"
#include "citra_qt/util/util.h" #include "citra_qt/util/util.h"
#include "common/vector_math.h" #include "common/vector_math.h"
#include "core/core.h"
#include "core/memory.h" #include "core/memory.h"
#include "video_core/debug_utils/debug_utils.h" #include "video_core/debug_utils/debug_utils.h"
#include "video_core/pica_state.h" #include "video_core/pica_state.h"
@ -166,7 +167,7 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
const auto format = texture.format; const auto format = texture.format;
const auto info = Pica::Texture::TextureInfo::FromPicaRegister(config, format); const auto info = Pica::Texture::TextureInfo::FromPicaRegister(config, format);
const u8* src = memory.GetPhysicalPointer(config.GetPhysicalAddress()); const u8* src = system.Memory().GetPhysicalPointer(config.GetPhysicalAddress());
new_info_widget = new TextureInfoWidget(src, info); new_info_widget = new TextureInfoWidget(src, info);
} }
if (command_info_widget) { if (command_info_widget) {
@ -180,8 +181,8 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
} }
#undef COMMAND_IN_RANGE #undef COMMAND_IN_RANGE
GPUCommandListWidget::GPUCommandListWidget(Memory::MemorySystem& memory_, QWidget* parent) GPUCommandListWidget::GPUCommandListWidget(Core::System& system_, QWidget* parent)
: QDockWidget(tr("Pica Command List"), parent), memory{memory_} { : QDockWidget(tr("Pica Command List"), parent), system{system_} {
setObjectName(QStringLiteral("Pica Command List")); setObjectName(QStringLiteral("Pica Command List"));
GPUCommandListModel* model = new GPUCommandListModel(this); GPUCommandListModel* model = new GPUCommandListModel(this);

View File

@ -11,8 +11,8 @@
class QPushButton; class QPushButton;
class QTreeView; class QTreeView;
namespace Memory { namespace Core {
class MemorySystem; class System;
} }
class GPUCommandListModel : public QAbstractListModel { class GPUCommandListModel : public QAbstractListModel {
@ -42,7 +42,7 @@ class GPUCommandListWidget : public QDockWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit GPUCommandListWidget(Memory::MemorySystem& memory, QWidget* parent = nullptr); explicit GPUCommandListWidget(Core::System& system, QWidget* parent = nullptr);
public slots: public slots:
void OnToggleTracing(); void OnToggleTracing();
@ -57,7 +57,7 @@ signals:
private: private:
std::unique_ptr<Pica::DebugUtils::PicaTrace> pica_trace; std::unique_ptr<Pica::DebugUtils::PicaTrace> pica_trace;
Memory::MemorySystem& memory; Core::System& system;
QTreeView* list_widget; QTreeView* list_widget;
QWidget* command_info_widget; QWidget* command_info_widget;
QPushButton* toggle_tracing; QPushButton* toggle_tracing;

View File

@ -448,7 +448,7 @@ void GMainWindow::InitializeDebugWidgets() {
graphicsWidget->hide(); graphicsWidget->hide();
debug_menu->addAction(graphicsWidget->toggleViewAction()); debug_menu->addAction(graphicsWidget->toggleViewAction());
graphicsCommandsWidget = new GPUCommandListWidget(system.Memory(), this); graphicsCommandsWidget = new GPUCommandListWidget(system, this);
addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget); addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget);
graphicsCommandsWidget->hide(); graphicsCommandsWidget->hide();
debug_menu->addAction(graphicsCommandsWidget->toggleViewAction()); debug_menu->addAction(graphicsCommandsWidget->toggleViewAction());
@ -627,6 +627,8 @@ void GMainWindow::InitializeHotkeys() {
Settings::values.frame_limit.SetGlobal(!Settings::values.frame_limit.UsingGlobal()); Settings::values.frame_limit.SetGlobal(!Settings::values.frame_limit.UsingGlobal());
UpdateStatusBar(); UpdateStatusBar();
}); });
connect_shortcut(QStringLiteral("Swap Eyes"),
[&] { Settings::values.swap_eyes = !Settings::values.swap_eyes; });
connect_shortcut(QStringLiteral("Toggle Texture Dumping"), connect_shortcut(QStringLiteral("Toggle Texture Dumping"),
[&] { Settings::values.dump_textures = !Settings::values.dump_textures; }); [&] { Settings::values.dump_textures = !Settings::values.dump_textures; });
connect_shortcut(QStringLiteral("Toggle Custom Textures"), connect_shortcut(QStringLiteral("Toggle Custom Textures"),
@ -2482,18 +2484,24 @@ void GMainWindow::OnMouseActivity() {
ShowMouseCursor(); ShowMouseCursor();
} }
void GMainWindow::mouseMoveEvent([[maybe_unused]] QMouseEvent* event) { void GMainWindow::mouseMoveEvent(QMouseEvent*) {
OnMouseActivity(); OnMouseActivity();
} }
void GMainWindow::mousePressEvent([[maybe_unused]] QMouseEvent* event) { void GMainWindow::mousePressEvent(QMouseEvent*) {
OnMouseActivity(); OnMouseActivity();
} }
void GMainWindow::mouseReleaseEvent([[maybe_unused]] QMouseEvent* event) { void GMainWindow::mouseReleaseEvent(QMouseEvent*) {
OnMouseActivity(); OnMouseActivity();
} }
void GMainWindow::moveEvent(QMoveEvent* event) {
QMainWindow::moveEvent(event);
const auto screen_pos = Common::MakeVec(pos().x(), pos().y());
render_window->SetScreenPos(screen_pos);
}
void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string details) { void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string details) {
QString status_message; QString status_message;

View File

@ -374,6 +374,7 @@ protected:
void mouseMoveEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override;
void mousePressEvent(QMouseEvent* event) override; void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override;
void moveEvent(QMoveEvent* event) override;
}; };
Q_DECLARE_METATYPE(std::size_t); Q_DECLARE_METATYPE(std::size_t);

View File

@ -84,7 +84,7 @@ void LogSettings() {
log_setting("Renderer_TextureFilter", GetTextureFilterName(values.texture_filter.GetValue())); log_setting("Renderer_TextureFilter", GetTextureFilterName(values.texture_filter.GetValue()));
log_setting("Stereoscopy_Render3d", values.render_3d.GetValue()); log_setting("Stereoscopy_Render3d", values.render_3d.GetValue());
log_setting("Stereoscopy_Factor3d", values.factor_3d.GetValue()); log_setting("Stereoscopy_Factor3d", values.factor_3d.GetValue());
log_setting("Stereoscopy_MonoRenderOption", values.mono_render_option.GetValue()); log_setting("Stereoscopy_SwapEyes", values.swap_eyes.GetValue());
if (values.render_3d.GetValue() == StereoRenderOption::Anaglyph) { if (values.render_3d.GetValue() == StereoRenderOption::Anaglyph) {
log_setting("Renderer_AnaglyphShader", values.anaglyph_shader_name.GetValue()); log_setting("Renderer_AnaglyphShader", values.anaglyph_shader_name.GetValue());
} }

View File

@ -49,19 +49,12 @@ enum class LayoutOption : u32 {
enum class StereoRenderOption : u32 { enum class StereoRenderOption : u32 {
Off = 0, Off = 0,
SideBySide = 1, SideBySide = 1,
Anaglyph = 2, TopBottom = 2,
Interlaced = 3, Anaglyph = 3,
ReverseInterlaced = 4, Interlaced = 4,
CardboardVR = 5 CardboardVR = 5
}; };
// Which eye to render when 3d is off. 800px wide mode could be added here in the future, when
// implemented
enum class MonoRenderOption : u32 {
LeftEye = 0,
RightEye = 1,
};
enum class AudioEmulation : u32 { enum class AudioEmulation : u32 {
HLE = 0, HLE = 0,
LLE = 1, LLE = 1,
@ -467,8 +460,7 @@ struct Values {
SwitchableSetting<StereoRenderOption> render_3d{StereoRenderOption::Off, "render_3d"}; SwitchableSetting<StereoRenderOption> render_3d{StereoRenderOption::Off, "render_3d"};
SwitchableSetting<u32> factor_3d{0, "factor_3d"}; SwitchableSetting<u32> factor_3d{0, "factor_3d"};
SwitchableSetting<MonoRenderOption> mono_render_option{MonoRenderOption::LeftEye, SwitchableSetting<bool> swap_eyes{false, "swap_eyes"};
"mono_render_option"};
Setting<u32> cardboard_screen_size{85, "cardboard_screen_size"}; Setting<u32> cardboard_screen_size{85, "cardboard_screen_size"};
Setting<s32> cardboard_x_shift{0, "cardboard_x_shift"}; Setting<s32> cardboard_x_shift{0, "cardboard_x_shift"};

View File

@ -461,14 +461,6 @@ add_library(citra_core STATIC
perf_stats.cpp perf_stats.cpp
perf_stats.h perf_stats.h
precompiled_headers.h precompiled_headers.h
rpc/packet.cpp
rpc/packet.h
rpc/rpc_server.cpp
rpc/rpc_server.h
rpc/server.cpp
rpc/server.h
rpc/udp_server.cpp
rpc/udp_server.h
savestate.cpp savestate.cpp
savestate.h savestate.h
system_titles.cpp system_titles.cpp
@ -483,18 +475,32 @@ add_library(citra_core STATIC
create_target_directory_groups(citra_core) create_target_directory_groups(citra_core)
target_link_libraries(citra_core PUBLIC citra_common PRIVATE audio_core network video_core) target_link_libraries(citra_core PUBLIC citra_common PRIVATE audio_core network video_core)
target_link_libraries(citra_core PRIVATE Boost::boost Boost::serialization Boost::iostreams) target_link_libraries(citra_core PRIVATE Boost::boost Boost::serialization Boost::iostreams httplib)
target_link_libraries(citra_core PUBLIC dds-ktx PRIVATE cryptopp fmt::fmt lodepng open_source_archives) target_link_libraries(citra_core PUBLIC dds-ktx PRIVATE cryptopp fmt::fmt lodepng open_source_archives)
set_target_properties(citra_core PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO}) set_target_properties(citra_core PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO})
if (ENABLE_WEB_SERVICE) if (ENABLE_WEB_SERVICE)
target_compile_definitions(citra_core PRIVATE -DENABLE_WEB_SERVICE -DCPPHTTPLIB_OPENSSL_SUPPORT) target_compile_definitions(citra_core PRIVATE -DENABLE_WEB_SERVICE)
target_link_libraries(citra_core PRIVATE web_service ${OPENSSL_LIBS} httplib) target_link_libraries(citra_core PRIVATE web_service)
if (ANDROID) if (ANDROID)
target_link_libraries(citra_core PRIVATE ifaddrs) target_link_libraries(citra_core PRIVATE ifaddrs)
endif() endif()
endif() endif()
if (ENABLE_SCRIPTING)
target_compile_definitions(citra_core PRIVATE -DENABLE_SCRIPTING)
target_sources(citra_core PRIVATE
rpc/packet.cpp
rpc/packet.h
rpc/rpc_server.cpp
rpc/rpc_server.h
rpc/server.cpp
rpc/server.h
rpc/udp_server.cpp
rpc/udp_server.h
)
endif()
if ("x86_64" IN_LIST ARCHITECTURE OR "arm64" IN_LIST ARCHITECTURE) if ("x86_64" IN_LIST ARCHITECTURE OR "arm64" IN_LIST ARCHITECTURE)
target_sources(citra_core PRIVATE target_sources(citra_core PRIVATE
arm/dynarmic/arm_dynarmic.cpp arm/dynarmic/arm_dynarmic.cpp

View File

@ -45,7 +45,9 @@
#include "core/hw/lcd.h" #include "core/hw/lcd.h"
#include "core/loader/loader.h" #include "core/loader/loader.h"
#include "core/movie.h" #include "core/movie.h"
#ifdef ENABLE_SCRIPTING
#include "core/rpc/server.h" #include "core/rpc/server.h"
#endif
#include "core/telemetry_session.h" #include "core/telemetry_session.h"
#include "network/network.h" #include "network/network.h"
#include "video_core/custom_textures/custom_tex_manager.h" #include "video_core/custom_textures/custom_tex_manager.h"
@ -418,7 +420,9 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window,
telemetry_session = std::make_unique<Core::TelemetrySession>(); telemetry_session = std::make_unique<Core::TelemetrySession>();
#ifdef ENABLE_SCRIPTING
rpc_server = std::make_unique<RPC::Server>(*this); rpc_server = std::make_unique<RPC::Server>(*this);
#endif
service_manager = std::make_unique<Service::SM::ServiceManager>(*this); service_manager = std::make_unique<Service::SM::ServiceManager>(*this);
archive_manager = std::make_unique<Service::FS::ArchiveManager>(*this); archive_manager = std::make_unique<Service::FS::ArchiveManager>(*this);
@ -555,7 +559,9 @@ void System::Shutdown(bool is_deserializing) {
} }
custom_tex_manager.reset(); custom_tex_manager.reset();
telemetry_session.reset(); telemetry_session.reset();
#ifdef ENABLE_SCRIPTING
rpc_server.reset(); rpc_server.reset();
#endif
archive_manager.reset(); archive_manager.reset();
service_manager.reset(); service_manager.reset();
dsp_core.reset(); dsp_core.reset();

View File

@ -405,8 +405,10 @@ private:
/// Image interface /// Image interface
std::shared_ptr<Frontend::ImageInterface> registered_image_interface; std::shared_ptr<Frontend::ImageInterface> registered_image_interface;
#ifdef ENABLE_SCRIPTING
/// RPC Server for scripting support /// RPC Server for scripting support
std::unique_ptr<RPC::Server> rpc_server; std::unique_ptr<RPC::Server> rpc_server;
#endif
std::unique_ptr<Service::FS::ArchiveManager> archive_manager; std::unique_ptr<Service::FS::ArchiveManager> archive_manager;

View File

@ -73,6 +73,13 @@ bool EmuWindow::IsWithinTouchscreen(const Layout::FramebufferLayout& layout, uns
framebuffer_x < layout.bottom_screen.right / 2) || framebuffer_x < layout.bottom_screen.right / 2) ||
(framebuffer_x >= (layout.bottom_screen.left / 2) + (layout.width / 2) && (framebuffer_x >= (layout.bottom_screen.left / 2) + (layout.width / 2) &&
framebuffer_x < (layout.bottom_screen.right / 2) + (layout.width / 2)))); framebuffer_x < (layout.bottom_screen.right / 2) + (layout.width / 2))));
} else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::TopBottom) {
return framebuffer_x >= layout.bottom_screen.left &&
framebuffer_x < layout.bottom_screen.right &&
((framebuffer_y >= layout.bottom_screen.top / 2 &&
framebuffer_y < layout.bottom_screen.bottom / 2) ||
(framebuffer_y >= (layout.bottom_screen.top / 2) + (layout.height / 2) &&
framebuffer_y < (layout.bottom_screen.bottom / 2) + (layout.height / 2)));
} else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) { } else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) {
return (framebuffer_y >= layout.bottom_screen.top && return (framebuffer_y >= layout.bottom_screen.top &&
framebuffer_y < layout.bottom_screen.bottom && framebuffer_y < layout.bottom_screen.bottom &&
@ -91,22 +98,35 @@ bool EmuWindow::IsWithinTouchscreen(const Layout::FramebufferLayout& layout, uns
std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const { std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const {
if (new_x >= framebuffer_layout.width / 2) { if (new_x >= framebuffer_layout.width / 2) {
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) {
new_x -= framebuffer_layout.width / 2; new_x -= framebuffer_layout.width / 2;
else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) } else if (Settings::values.render_3d.GetValue() ==
Settings::StereoRenderOption::CardboardVR) {
new_x -= new_x -=
(framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2);
} }
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) { }
new_x = std::max(new_x, framebuffer_layout.bottom_screen.left / 2); if (new_y >= framebuffer_layout.height / 2) {
new_x = std::min(new_x, framebuffer_layout.bottom_screen.right / 2 - 1); if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::TopBottom) {
} else { new_y -= framebuffer_layout.height / 2;
new_x = std::max(new_x, framebuffer_layout.bottom_screen.left); }
new_x = std::min(new_x, framebuffer_layout.bottom_screen.right - 1);
} }
new_y = std::max(new_y, framebuffer_layout.bottom_screen.top); if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) {
new_y = std::min(new_y, framebuffer_layout.bottom_screen.bottom - 1); new_x = std::clamp(new_x, framebuffer_layout.bottom_screen.left / 2,
framebuffer_layout.bottom_screen.right / 2 - 1);
} else {
new_x = std::clamp(new_x, framebuffer_layout.bottom_screen.left,
framebuffer_layout.bottom_screen.right - 1);
}
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::TopBottom) {
new_y = std::clamp(new_y, framebuffer_layout.bottom_screen.top / 2,
framebuffer_layout.bottom_screen.bottom / 2 - 1);
} else {
new_y = std::clamp(new_y, framebuffer_layout.bottom_screen.top,
framebuffer_layout.bottom_screen.bottom - 1);
}
return std::make_tuple(new_x, new_y); return std::make_tuple(new_x, new_y);
} }
@ -122,17 +142,25 @@ void EmuWindow::CreateTouchState() {
} }
bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) {
return false; return false;
}
if (framebuffer_x >= framebuffer_layout.width / 2) { if (framebuffer_x >= framebuffer_layout.width / 2) {
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) {
framebuffer_x -= framebuffer_layout.width / 2; framebuffer_x -= framebuffer_layout.width / 2;
else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) } else if (Settings::values.render_3d.GetValue() ==
Settings::StereoRenderOption::CardboardVR) {
framebuffer_x -= framebuffer_x -=
(framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2);
} }
std::lock_guard guard(touch_state->mutex); }
if (framebuffer_y >= framebuffer_layout.height / 2) {
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::TopBottom) {
framebuffer_y -= framebuffer_layout.height / 2;
}
}
std::scoped_lock lock{touch_state->mutex};
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) { if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) {
touch_state->touch_x = touch_state->touch_x =
static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left / 2) / static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left / 2) /
@ -143,9 +171,17 @@ bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left) / static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left) /
(framebuffer_layout.bottom_screen.right - framebuffer_layout.bottom_screen.left); (framebuffer_layout.bottom_screen.right - framebuffer_layout.bottom_screen.left);
} }
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::TopBottom) {
touch_state->touch_y =
static_cast<float>(framebuffer_y - framebuffer_layout.bottom_screen.top / 2) /
(framebuffer_layout.bottom_screen.bottom / 2 -
framebuffer_layout.bottom_screen.top / 2);
} else {
touch_state->touch_y = touch_state->touch_y =
static_cast<float>(framebuffer_y - framebuffer_layout.bottom_screen.top) / static_cast<float>(framebuffer_y - framebuffer_layout.bottom_screen.top) /
(framebuffer_layout.bottom_screen.bottom - framebuffer_layout.bottom_screen.top); (framebuffer_layout.bottom_screen.bottom - framebuffer_layout.bottom_screen.top);
}
if (!framebuffer_layout.is_rotated) { if (!framebuffer_layout.is_rotated) {
std::swap(touch_state->touch_x, touch_state->touch_y); std::swap(touch_state->touch_x, touch_state->touch_y);
@ -157,18 +193,20 @@ bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
} }
void EmuWindow::TouchReleased() { void EmuWindow::TouchReleased() {
std::lock_guard guard{touch_state->mutex}; std::scoped_lock lock{touch_state->mutex};
touch_state->touch_pressed = false; touch_state->touch_pressed = false;
touch_state->touch_x = 0; touch_state->touch_x = 0;
touch_state->touch_y = 0; touch_state->touch_y = 0;
} }
void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) { void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) {
if (!touch_state->touch_pressed) if (!touch_state->touch_pressed) {
return; return;
}
if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) {
std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y); std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y);
}
TouchPressed(framebuffer_x, framebuffer_y); TouchPressed(framebuffer_x, framebuffer_y);
} }

View File

@ -9,6 +9,7 @@
#include <utility> #include <utility>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/vector_math.h"
#include "core/3ds.h" #include "core/3ds.h"
#include "core/frontend/framebuffer_layout.h" #include "core/frontend/framebuffer_layout.h"
@ -217,6 +218,17 @@ public:
config = val; config = val;
} }
/**
* Updates the position of the client window area relative to the origin of the host display.
*/
void SetScreenPos(const Common::Vec2i pos) {
screen_pos = pos;
}
Common::Vec2i GetScreenPos() const {
return screen_pos;
}
/** /**
* Returns system information about the drawing area. * Returns system information about the drawing area.
*/ */
@ -274,6 +286,7 @@ protected:
bool is_secondary{}; bool is_secondary{};
bool strict_context_required{}; bool strict_context_required{};
WindowSystemInfo window_info; WindowSystemInfo window_info;
Common::Vec2i screen_pos{};
private: private:
/** /**

View File

@ -4,6 +4,7 @@
#include <cmath> #include <cmath>
#include "common/alignment.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/settings.h" #include "common/settings.h"
#include "core/3ds.h" #include "core/3ds.h"

View File

@ -77,7 +77,6 @@ static std::pair<std::string, std::string> SplitUrl(const std::string& url) {
void Context::MakeRequest() { void Context::MakeRequest() {
ASSERT(state == RequestState::NotStarted); ASSERT(state == RequestState::NotStarted);
#ifdef ENABLE_WEB_SERVICE
const auto& [host, path] = SplitUrl(url); const auto& [host, path] = SplitUrl(url);
const auto client = std::make_unique<httplib::Client>(host); const auto client = std::make_unique<httplib::Client>(host);
SSL_CTX* ctx = client->ssl_context(); SSL_CTX* ctx = client->ssl_context();
@ -128,10 +127,6 @@ void Context::MakeRequest() {
// TODO(B3N30): Verify this state on HW // TODO(B3N30): Verify this state on HW
state = RequestState::ReadyToDownloadContent; state = RequestState::ReadyToDownloadContent;
} }
#else
LOG_ERROR(Service_HTTP, "Tried to make request but WebServices is not enabled in this build");
state = RequestState::TimedOut;
#endif
} }
void HTTP_C::Initialize(Kernel::HLERequestContext& ctx) { void HTTP_C::Initialize(Kernel::HLERequestContext& ctx) {

View File

@ -17,12 +17,10 @@
#include <boost/serialization/unordered_map.hpp> #include <boost/serialization/unordered_map.hpp>
#include <boost/serialization/vector.hpp> #include <boost/serialization/vector.hpp>
#include <boost/serialization/weak_ptr.hpp> #include <boost/serialization/weak_ptr.hpp>
#ifdef ENABLE_WEB_SERVICE
#if defined(__ANDROID__) #if defined(__ANDROID__)
#include <ifaddrs.h> #include <ifaddrs.h>
#endif #endif
#include <httplib.h> #include <httplib.h>
#endif
#include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/shared_memory.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
@ -217,9 +215,7 @@ public:
std::future<void> request_future; std::future<void> request_future;
std::atomic<u64> current_download_size_bytes; std::atomic<u64> current_download_size_bytes;
std::atomic<u64> total_download_size_bytes; std::atomic<u64> total_download_size_bytes;
#ifdef ENABLE_WEB_SERVICE
httplib::Response response; httplib::Response response;
#endif
}; };
struct SessionData : public Kernel::SessionRequestHandler::SessionDataBase { struct SessionData : public Kernel::SessionRequestHandler::SessionDataBase {

View File

@ -151,8 +151,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {
static_cast<int>(Settings::values.render_3d.GetValue())); static_cast<int>(Settings::values.render_3d.GetValue()));
AddField(Telemetry::FieldType::UserConfig, "Renderer_Factor3d", AddField(Telemetry::FieldType::UserConfig, "Renderer_Factor3d",
Settings::values.factor_3d.GetValue()); Settings::values.factor_3d.GetValue());
AddField(Telemetry::FieldType::UserConfig, "Renderer_MonoRenderOption", AddField(Telemetry::FieldType::UserConfig, "Renderer_SwapEyes",
static_cast<int>(Settings::values.mono_render_option.GetValue())); static_cast<int>(Settings::values.swap_eyes.GetValue()));
AddField(Telemetry::FieldType::UserConfig, "System_IsNew3ds", AddField(Telemetry::FieldType::UserConfig, "System_IsNew3ds",
Settings::values.is_new_3ds.GetValue()); Settings::values.is_new_3ds.GetValue());
AddField(Telemetry::FieldType::UserConfig, "System_RegionValue", AddField(Telemetry::FieldType::UserConfig, "System_RegionValue",

View File

@ -19,14 +19,14 @@ add_library(network STATIC
create_target_directory_groups(network) create_target_directory_groups(network)
if (ENABLE_WEB_SERVICE) if (ENABLE_WEB_SERVICE)
target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE -DCPPHTTPLIB_OPENSSL_SUPPORT) target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE)
target_link_libraries(network PRIVATE web_service httplib) target_link_libraries(network PRIVATE web_service)
if (ANDROID) if (ANDROID)
target_link_libraries(network PRIVATE ifaddrs) target_link_libraries(network PRIVATE ifaddrs)
endif() endif()
endif() endif()
target_link_libraries(network PRIVATE citra_common enet Boost::serialization) target_link_libraries(network PRIVATE citra_common enet Boost::serialization httplib)
set_target_properties(network PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO}) set_target_properties(network PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO})
if (CITRA_USE_PRECOMPILED_HEADERS) if (CITRA_USE_PRECOMPILED_HEADERS)

View File

@ -4,17 +4,16 @@
//? #version 430 core //? #version 430 core
// Anaglyph Red-Cyan shader based on Dubois algorithm // https://cybereality.com/rendepth-red-cyan-anaglyph-filter-optimized-for-stereoscopic-3d-on-lcd-monitors/
// Constants taken from the paper: const mat3 left_filter = mat3(
// "Conversion of a Stereo Pair to Anaglyph with vec3(0.4561, 0.500484, 0.176381),
// the Least-Squares Projection Method" vec3(-0.400822, -0.0378246, -0.0157589),
// Eric Dubois, March 2009 vec3(-0.0152161, -0.0205971, -0.00546856));
const mat3 l = mat3( 0.437, 0.449, 0.164,
-0.062,-0.062,-0.024, const mat3 right_filter = mat3(
-0.048,-0.050,-0.017); vec3(-0.0434706, -0.0879388, -0.00155529),
const mat3 r = mat3(-0.011,-0.032,-0.007, vec3(0.378476, 0.73364, -0.0184503),
0.377, 0.761, 0.009, vec3(-0.0721527, -0.112961, 1.2264));
-0.026,-0.093, 1.234);
layout(location = 0) in vec2 frag_tex_coord; layout(location = 0) in vec2 frag_tex_coord;
layout(location = 0) out vec4 color; layout(location = 0) out vec4 color;
@ -24,9 +23,22 @@ layout(binding = 1) uniform sampler2D color_texture_r;
uniform vec4 resolution; uniform vec4 resolution;
uniform int layer; uniform int layer;
uniform bool swap_eyes;
const vec3 gamma_map = vec3(1.6, 0.8, 1.0);
vec3 correct_color(vec3 original) {
vec3 corrected;
corrected.r = pow(original.r, 1.0 / gamma_map.r);
corrected.g = pow(original.g, 1.0 / gamma_map.g);
corrected.b = pow(original.b, 1.0 / gamma_map.b);
return corrected;
}
void main() { void main() {
vec4 color_tex_l = texture(color_texture, frag_tex_coord); vec4 color_left = texture(color_texture, frag_tex_coord);
vec4 color_tex_r = texture(color_texture_r, frag_tex_coord); vec4 color_right = texture(color_texture_r, frag_tex_coord);
color = vec4(color_tex_l.rgb*l+color_tex_r.rgb*r, color_tex_l.a); vec3 optimized_color = clamp(color_left.rgb * (swap_eyes ? right_filter : left_filter), vec3(0.0), vec3(1.0)) +
clamp(color_right.rgb * (swap_eyes ? left_filter : right_filter), vec3(0.0), vec3(1.0));
color = vec4(correct_color(optimized_color), color_left.a);
} }

View File

@ -7,16 +7,22 @@
layout(location = 0) in vec2 frag_tex_coord; layout(location = 0) in vec2 frag_tex_coord;
layout(location = 0) out vec4 color; layout(location = 0) out vec4 color;
layout(binding = 0) uniform sampler2D color_texture; layout(binding = 0) uniform sampler2D color_texture_l;
layout(binding = 1) uniform sampler2D color_texture_r; layout(binding = 1) uniform sampler2D color_texture_r;
uniform vec4 o_resolution; uniform vec4 o_resolution;
uniform int reverse_interlaced; uniform ivec2 screen_pos;
uniform bool swap_eyes;
void main() { void main() {
float screen_row = o_resolution.x * frag_tex_coord.x; float screen_row = o_resolution.x * frag_tex_coord.x;
if (int(screen_row) % 2 == reverse_interlaced) bool is_even = screen_pos.y % 2 == 0;
color = texture(color_texture, frag_tex_coord); if (swap_eyes) {
else is_even = !is_even;
}
if (int(screen_row) % 2 == int(is_even)) {
color = texture(color_texture_l, frag_tex_coord);
} else {
color = texture(color_texture_r, frag_tex_coord); color = texture(color_texture_r, frag_tex_coord);
}
} }

View File

@ -49,6 +49,8 @@ uniform float4 i_resolution;
uniform float4 o_resolution; uniform float4 o_resolution;
// Layer // Layer
uniform int layer; uniform int layer;
// Screen position
uniform int2 screen_pos;
uniform sampler2D color_texture; uniform sampler2D color_texture;
uniform sampler2D color_texture_r; uniform sampler2D color_texture_r;
@ -119,6 +121,11 @@ float2 GetCoordinates()
return frag_tex_coord; return frag_tex_coord;
} }
int2 GetScreenPos()
{
return screen_pos;
}
void SetOutput(float4 color_in) void SetOutput(float4 color_in)
{ {
color = color_in; color = color_in;

View File

@ -54,8 +54,7 @@ struct ScreenRectVertex {
* *
* @param flipped Whether the frame should be flipped upside down. * @param flipped Whether the frame should be flipped upside down.
*/ */
static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, const float height, static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(u32 width, u32 height, bool flipped) {
bool flipped) {
std::array<GLfloat, 3 * 2> matrix; // Laid out in column-major order std::array<GLfloat, 3 * 2> matrix; // Laid out in column-major order
@ -405,9 +404,7 @@ void RendererOpenGL::ReloadShader() {
shader_data += shader_text; shader_data += shader_text;
} }
} }
} else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || } else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced) {
Settings::values.render_3d.GetValue() ==
Settings::StereoRenderOption::ReverseInterlaced) {
shader_data += HostShaders::OPENGL_PRESENT_INTERLACED_FRAG; shader_data += HostShaders::OPENGL_PRESENT_INTERLACED_FRAG;
} else { } else {
if (Settings::values.pp_shader_name.GetValue() == "none (builtin)") { if (Settings::values.pp_shader_name.GetValue() == "none (builtin)") {
@ -429,23 +426,14 @@ void RendererOpenGL::ReloadShader() {
uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix"); uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix");
uniform_color_texture = glGetUniformLocation(shader.handle, "color_texture"); uniform_color_texture = glGetUniformLocation(shader.handle, "color_texture");
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph || if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph ||
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced) {
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced) { uniform_swap_eyes = glGetUniformLocation(shader.handle, "swap_eyes");
uniform_color_texture_r = glGetUniformLocation(shader.handle, "color_texture_r"); uniform_color_texture_r = glGetUniformLocation(shader.handle, "color_texture_r");
} }
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced ||
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced) {
GLuint uniform_reverse_interlaced =
glGetUniformLocation(shader.handle, "reverse_interlaced");
if (Settings::values.render_3d.GetValue() ==
Settings::StereoRenderOption::ReverseInterlaced)
glUniform1i(uniform_reverse_interlaced, 1);
else
glUniform1i(uniform_reverse_interlaced, 0);
}
uniform_i_resolution = glGetUniformLocation(shader.handle, "i_resolution"); uniform_i_resolution = glGetUniformLocation(shader.handle, "i_resolution");
uniform_o_resolution = glGetUniformLocation(shader.handle, "o_resolution"); uniform_o_resolution = glGetUniformLocation(shader.handle, "o_resolution");
uniform_layer = glGetUniformLocation(shader.handle, "layer"); uniform_layer = glGetUniformLocation(shader.handle, "layer");
uniform_screen_pos = glGetUniformLocation(shader.handle, "screen_pos");
attrib_position = glGetAttribLocation(shader.handle, "vert_position"); attrib_position = glGetAttribLocation(shader.handle, "vert_position");
attrib_tex_coord = glGetAttribLocation(shader.handle, "vert_tex_coord"); attrib_tex_coord = glGetAttribLocation(shader.handle, "vert_tex_coord");
} }
@ -678,8 +666,7 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
// Set projection matrix // Set projection matrix
std::array<GLfloat, 3 * 2> ortho_matrix = const auto ortho_matrix = MakeOrthographicMatrix(layout.width, layout.height, flipped);
MakeOrthographicMatrix((float)layout.width, (float)layout.height, flipped);
glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data());
// Bind texture in Texture Unit 0 // Bind texture in Texture Unit 0
@ -687,8 +674,12 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
const bool stereo_single_screen = const bool stereo_single_screen =
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph || Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph ||
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced;
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced;
// Set the screen position
const auto screen_pos = render_window.GetScreenPos() +
Common::MakeVec<s32>(layout.top_screen.left, layout.top_screen.bottom);
glUniform2i(uniform_screen_pos, screen_pos.x, screen_pos.y);
// Bind a second texture for the right eye if in Anaglyph mode // Bind a second texture for the right eye if in Anaglyph mode
if (stereo_single_screen) { if (stereo_single_screen) {
@ -756,7 +747,7 @@ void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout,
: Layout::DisplayOrientation::Portrait; : Layout::DisplayOrientation::Portrait;
switch (Settings::values.render_3d.GetValue()) { switch (Settings::values.render_3d.GetValue()) {
case Settings::StereoRenderOption::Off: { case Settings::StereoRenderOption::Off: {
const int eye = static_cast<int>(Settings::values.mono_render_option.GetValue()); const u32 eye = static_cast<u32>(Settings::values.swap_eyes.GetValue());
DrawSingleScreen(screen_infos[eye], top_screen_left, top_screen_top, top_screen_width, DrawSingleScreen(screen_infos[eye], top_screen_left, top_screen_top, top_screen_width,
top_screen_height, orientation); top_screen_height, orientation);
break; break;
@ -770,6 +761,15 @@ void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout,
top_screen_top, top_screen_width / 2, top_screen_height, orientation); top_screen_top, top_screen_width / 2, top_screen_height, orientation);
break; break;
} }
case Settings::StereoRenderOption::TopBottom: {
DrawSingleScreen(screen_infos[0], top_screen_left, top_screen_top / 2, top_screen_width,
top_screen_height / 2, orientation);
glUniform1i(uniform_layer, 1);
DrawSingleScreen(screen_infos[1], top_screen_left,
static_cast<float>((top_screen_top / 2) + (layout.height / 2)),
top_screen_width, top_screen_height / 2, orientation);
break;
}
case Settings::StereoRenderOption::CardboardVR: { case Settings::StereoRenderOption::CardboardVR: {
DrawSingleScreen(screen_infos[0], top_screen_left, top_screen_top, top_screen_width, DrawSingleScreen(screen_infos[0], top_screen_left, top_screen_top, top_screen_width,
top_screen_height, orientation); top_screen_height, orientation);
@ -781,8 +781,8 @@ void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout,
break; break;
} }
case Settings::StereoRenderOption::Anaglyph: case Settings::StereoRenderOption::Anaglyph:
case Settings::StereoRenderOption::Interlaced: case Settings::StereoRenderOption::Interlaced: {
case Settings::StereoRenderOption::ReverseInterlaced: { glUniform1i(uniform_swap_eyes, Settings::values.swap_eyes.GetValue());
DrawSingleScreenStereo(screen_infos[0], screen_infos[1], top_screen_left, top_screen_top, DrawSingleScreenStereo(screen_infos[0], screen_infos[1], top_screen_left, top_screen_top,
top_screen_width, top_screen_height, orientation); top_screen_width, top_screen_height, orientation);
break; break;
@ -803,8 +803,17 @@ void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout,
const auto orientation = layout.is_rotated ? Layout::DisplayOrientation::Landscape const auto orientation = layout.is_rotated ? Layout::DisplayOrientation::Landscape
: Layout::DisplayOrientation::Portrait; : Layout::DisplayOrientation::Portrait;
const auto render_3d =
#ifndef ANDROID
Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows &&
Settings::values.render_3d.GetValue() != Settings::StereoRenderOption::Anaglyph
? Settings::StereoRenderOption::Off
: Settings::values.render_3d.GetValue();
#else
const auto render_3d = Settings::values.render_3d.GetValue();
#endif
switch (Settings::values.render_3d.GetValue()) { switch (render_3d) {
case Settings::StereoRenderOption::Off: { case Settings::StereoRenderOption::Off: {
DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top, DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top,
bottom_screen_width, bottom_screen_height, orientation); bottom_screen_width, bottom_screen_height, orientation);
@ -819,6 +828,15 @@ void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout,
bottom_screen_top, bottom_screen_width / 2, bottom_screen_height, orientation); bottom_screen_top, bottom_screen_width / 2, bottom_screen_height, orientation);
break; break;
} }
case Settings::StereoRenderOption::TopBottom: {
DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top / 2,
bottom_screen_width, bottom_screen_height / 2, orientation);
glUniform1i(uniform_layer, 1);
DrawSingleScreen(screen_infos[2], bottom_screen_left,
static_cast<float>((bottom_screen_top / 2) + (layout.height / 2)),
bottom_screen_width, bottom_screen_height / 2, orientation);
break;
}
case Settings::StereoRenderOption::CardboardVR: { case Settings::StereoRenderOption::CardboardVR: {
DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top, DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top,
bottom_screen_width, bottom_screen_height, orientation); bottom_screen_width, bottom_screen_height, orientation);
@ -830,8 +848,8 @@ void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout,
break; break;
} }
case Settings::StereoRenderOption::Anaglyph: case Settings::StereoRenderOption::Anaglyph:
case Settings::StereoRenderOption::Interlaced: case Settings::StereoRenderOption::Interlaced: {
case Settings::StereoRenderOption::ReverseInterlaced: { glUniform1i(uniform_swap_eyes, Settings::values.swap_eyes.GetValue());
DrawSingleScreenStereo(screen_infos[2], screen_infos[2], bottom_screen_left, DrawSingleScreenStereo(screen_infos[2], screen_infos[2], bottom_screen_left,
bottom_screen_top, bottom_screen_width, bottom_screen_height, bottom_screen_top, bottom_screen_width, bottom_screen_height,
orientation); orientation);

View File

@ -103,11 +103,13 @@ private:
GLuint uniform_modelview_matrix; GLuint uniform_modelview_matrix;
GLuint uniform_color_texture; GLuint uniform_color_texture;
GLuint uniform_color_texture_r; GLuint uniform_color_texture_r;
GLuint uniform_swap_eyes;
// Shader uniform for Dolphin compatibility // Shader uniform for Dolphin compatibility
GLuint uniform_i_resolution; GLuint uniform_i_resolution;
GLuint uniform_o_resolution; GLuint uniform_o_resolution;
GLuint uniform_layer; GLuint uniform_layer;
GLuint uniform_screen_pos;
// Shader attribute input indices // Shader attribute input indices
GLuint attrib_position; GLuint attrib_position;

View File

@ -16,7 +16,6 @@ add_library(web_service STATIC
create_target_directory_groups(web_service) create_target_directory_groups(web_service)
target_compile_definitions(web_service PRIVATE -DCPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(web_service PRIVATE citra_common network json-headers httplib cpp-jwt) target_link_libraries(web_service PRIVATE citra_common network json-headers httplib cpp-jwt)
target_link_libraries(web_service PUBLIC ${OPENSSL_LIBS}) target_link_libraries(web_service PUBLIC ${OPENSSL_LIBS})
set_target_properties(web_service PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO}) set_target_properties(web_service PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO})