mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 22:29:39 -06:00
Move DolphinQt2 to DolphinQt
This commit is contained in:
222
Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp
Normal file
222
Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Graphics/AdvancedWidget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "Core/Config/GraphicsSettings.h"
|
||||
#include "Core/Config/SYSCONFSettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsBool.h"
|
||||
#include "DolphinQt/Config/Graphics/GraphicsChoice.h"
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
AdvancedWidget::AdvancedWidget(GraphicsWindow* parent) : GraphicsWidget(parent)
|
||||
{
|
||||
CreateWidgets();
|
||||
LoadSettings();
|
||||
ConnectWidgets();
|
||||
AddDescriptions();
|
||||
|
||||
connect(parent, &GraphicsWindow::BackendChanged, this, &AdvancedWidget::OnBackendChanged);
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||
[=](Core::State state) { OnEmulationStateChanged(state != Core::State::Uninitialized); });
|
||||
|
||||
OnBackendChanged();
|
||||
}
|
||||
|
||||
void AdvancedWidget::CreateWidgets()
|
||||
{
|
||||
auto* main_layout = new QVBoxLayout;
|
||||
|
||||
// Debugging
|
||||
auto* debugging_box = new QGroupBox(tr("Debugging"));
|
||||
auto* debugging_layout = new QGridLayout();
|
||||
debugging_box->setLayout(debugging_layout);
|
||||
|
||||
m_enable_wireframe = new GraphicsBool(tr("Enable Wireframe"), Config::GFX_ENABLE_WIREFRAME);
|
||||
m_show_statistics = new GraphicsBool(tr("Show Statistics"), Config::GFX_OVERLAY_STATS);
|
||||
m_enable_format_overlay =
|
||||
new GraphicsBool(tr("Texture Format Overlay"), Config::GFX_TEXFMT_OVERLAY_ENABLE);
|
||||
m_enable_api_validation =
|
||||
new GraphicsBool(tr("Enable API Validation Layers"), Config::GFX_ENABLE_VALIDATION_LAYER);
|
||||
|
||||
debugging_layout->addWidget(m_enable_wireframe, 0, 0);
|
||||
debugging_layout->addWidget(m_show_statistics, 0, 1);
|
||||
debugging_layout->addWidget(m_enable_format_overlay, 1, 0);
|
||||
debugging_layout->addWidget(m_enable_api_validation, 1, 1);
|
||||
|
||||
// Utility
|
||||
auto* utility_box = new QGroupBox(tr("Utility"));
|
||||
auto* utility_layout = new QGridLayout();
|
||||
utility_box->setLayout(utility_layout);
|
||||
|
||||
m_dump_textures = new GraphicsBool(tr("Dump Textures"), Config::GFX_DUMP_TEXTURES);
|
||||
m_load_custom_textures = new GraphicsBool(tr("Load Custom Textures"), Config::GFX_HIRES_TEXTURES);
|
||||
m_prefetch_custom_textures =
|
||||
new GraphicsBool(tr("Prefetch Custom Textures"), Config::GFX_CACHE_HIRES_TEXTURES);
|
||||
m_use_fullres_framedumps = new GraphicsBool(tr("Internal Resolution Frame Dumps"),
|
||||
Config::GFX_INTERNAL_RESOLUTION_FRAME_DUMPS);
|
||||
m_dump_efb_target = new GraphicsBool(tr("Dump EFB Target"), Config::GFX_DUMP_EFB_TARGET);
|
||||
m_disable_vram_copies =
|
||||
new GraphicsBool(tr("Disable EFB VRAM Copies"), Config::GFX_HACK_DISABLE_COPY_TO_VRAM);
|
||||
m_enable_freelook = new GraphicsBool(tr("Free Look"), Config::GFX_FREE_LOOK);
|
||||
m_dump_use_ffv1 = new GraphicsBool(tr("Frame Dumps Use FFV1"), Config::GFX_USE_FFV1);
|
||||
|
||||
utility_layout->addWidget(m_dump_textures, 0, 0);
|
||||
utility_layout->addWidget(m_load_custom_textures, 0, 1);
|
||||
utility_layout->addWidget(m_prefetch_custom_textures, 1, 0);
|
||||
utility_layout->addWidget(m_use_fullres_framedumps, 1, 1);
|
||||
utility_layout->addWidget(m_dump_efb_target, 2, 0);
|
||||
utility_layout->addWidget(m_disable_vram_copies, 2, 1);
|
||||
utility_layout->addWidget(m_enable_freelook, 3, 0);
|
||||
#if defined(HAVE_FFMPEG)
|
||||
utility_layout->addWidget(m_dump_use_ffv1, 3, 1);
|
||||
#endif
|
||||
|
||||
// Misc.
|
||||
auto* misc_box = new QGroupBox(tr("Misc"));
|
||||
auto* misc_layout = new QGridLayout();
|
||||
misc_box->setLayout(misc_layout);
|
||||
|
||||
m_enable_cropping = new GraphicsBool(tr("Crop"), Config::GFX_CROP);
|
||||
m_enable_prog_scan = new QCheckBox(tr("Enable Progressive Scan"));
|
||||
|
||||
misc_layout->addWidget(m_enable_cropping, 0, 0);
|
||||
misc_layout->addWidget(m_enable_prog_scan, 0, 1);
|
||||
|
||||
#ifdef _WIN32
|
||||
m_borderless_fullscreen =
|
||||
new GraphicsBool(tr("Borderless Fullscreen"), Config::GFX_BORDERLESS_FULLSCREEN);
|
||||
|
||||
misc_layout->addWidget(m_borderless_fullscreen, 1, 0);
|
||||
#endif
|
||||
|
||||
main_layout->addWidget(debugging_box);
|
||||
main_layout->addWidget(utility_box);
|
||||
main_layout->addWidget(misc_box);
|
||||
main_layout->addStretch();
|
||||
|
||||
setLayout(main_layout);
|
||||
}
|
||||
|
||||
void AdvancedWidget::ConnectWidgets()
|
||||
{
|
||||
connect(m_load_custom_textures, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings);
|
||||
connect(m_enable_prog_scan, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings);
|
||||
}
|
||||
|
||||
void AdvancedWidget::LoadSettings()
|
||||
{
|
||||
m_prefetch_custom_textures->setEnabled(Config::Get(Config::GFX_HIRES_TEXTURES));
|
||||
m_enable_prog_scan->setChecked(Config::Get(Config::SYSCONF_PROGRESSIVE_SCAN));
|
||||
}
|
||||
|
||||
void AdvancedWidget::SaveSettings()
|
||||
{
|
||||
const auto hires_enabled = Config::Get(Config::GFX_HIRES_TEXTURES);
|
||||
m_prefetch_custom_textures->setEnabled(hires_enabled);
|
||||
|
||||
Config::SetBase(Config::SYSCONF_PROGRESSIVE_SCAN, m_enable_prog_scan->isChecked());
|
||||
}
|
||||
|
||||
void AdvancedWidget::OnBackendChanged()
|
||||
{
|
||||
}
|
||||
|
||||
void AdvancedWidget::OnEmulationStateChanged(bool running)
|
||||
{
|
||||
m_enable_prog_scan->setEnabled(!running);
|
||||
}
|
||||
|
||||
void AdvancedWidget::AddDescriptions()
|
||||
{
|
||||
static const char TR_WIREFRAME_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Render the scene as a wireframe.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_SHOW_STATS_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Show various rendering statistics.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_TEXTURE_FORMAT_DECRIPTION[] =
|
||||
QT_TR_NOOP("Modify textures to show the format they're encoded in. Needs an emulation reset "
|
||||
"in most cases.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_VALIDATION_LAYER_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Enables validation of API calls made by the video backend, which may assist in "
|
||||
"debugging graphical issues.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_DUMP_TEXTURE_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Dump decoded game textures to User/Dump/Textures/<game_id>/.\n\nIf unsure, leave "
|
||||
"this unchecked.");
|
||||
static const char TR_LOAD_CUSTOM_TEXTURE_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Load custom textures from User/Load/Textures/<game_id>/.\n\nIf unsure, leave this "
|
||||
"unchecked.");
|
||||
static const char TR_CACHE_CUSTOM_TEXTURE_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Cache custom textures to system RAM on startup.\nThis can require exponentially "
|
||||
"more RAM but fixes possible stuttering.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_DUMP_EFB_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Dump the contents of EFB copies to User/Dump/Textures/.\n\nIf unsure, leave this "
|
||||
"unchecked.");
|
||||
static const char TR_DISABLE_VRAM_COPIES_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Disables the VRAM copy of the EFB, forcing a round-trip to RAM. Inhibits all "
|
||||
"upscaling.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_INTERNAL_RESOLUTION_FRAME_DUMPING_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Create frame dumps and screenshots at the internal resolution of the renderer, rather than "
|
||||
"the size of the window it is displayed within. If the aspect ratio is widescreen, the "
|
||||
"output "
|
||||
"image will be scaled horizontally to preserve the vertical resolution.\n\nIf unsure, leave "
|
||||
"this unchecked.");
|
||||
#if defined(HAVE_FFMPEG)
|
||||
static const char TR_USE_FFV1_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Encode frame dumps using the FFV1 codec.\n\nIf unsure, leave this unchecked.");
|
||||
#endif
|
||||
static const char TR_FREE_LOOK_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"This feature allows you to change the game's camera.\nMove the mouse while holding the "
|
||||
"right "
|
||||
"mouse button to pan and while holding the middle button to move.\nHold SHIFT and press "
|
||||
"one of "
|
||||
"the WASD keys to move the camera by a certain step distance (SHIFT+2 to move faster and "
|
||||
"SHIFT+1 to move slower). Press SHIFT+R to reset the camera and SHIFT+F to reset the "
|
||||
"speed.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_CROPPING_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Crop the picture from its native aspect ratio to 4:3 or "
|
||||
"16:9.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_PROGRESSIVE_SCAN_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Enables progressive scan if supported by the emulated software.\nMost games don't "
|
||||
"care about this.\n\nIf unsure, leave this unchecked.");
|
||||
#ifdef _WIN32
|
||||
static const char TR_BORDERLESS_FULLSCREEN_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Implement fullscreen mode with a borderless window spanning the whole screen instead of "
|
||||
"using "
|
||||
"exclusive mode.\nAllows for faster transitions between fullscreen and windowed mode, but "
|
||||
"slightly increases input latency, makes movement less smooth and slightly decreases "
|
||||
"performance.\nExclusive mode is required for Nvidia 3D Vision to work in the Direct3D "
|
||||
"backend.\n\nIf unsure, leave this unchecked.");
|
||||
#endif
|
||||
|
||||
AddDescription(m_enable_wireframe, TR_WIREFRAME_DESCRIPTION);
|
||||
AddDescription(m_show_statistics, TR_SHOW_STATS_DESCRIPTION);
|
||||
AddDescription(m_enable_format_overlay, TR_TEXTURE_FORMAT_DECRIPTION);
|
||||
AddDescription(m_enable_api_validation, TR_VALIDATION_LAYER_DESCRIPTION);
|
||||
AddDescription(m_dump_textures, TR_DUMP_TEXTURE_DESCRIPTION);
|
||||
AddDescription(m_load_custom_textures, TR_LOAD_CUSTOM_TEXTURE_DESCRIPTION);
|
||||
AddDescription(m_prefetch_custom_textures, TR_CACHE_CUSTOM_TEXTURE_DESCRIPTION);
|
||||
AddDescription(m_dump_efb_target, TR_DUMP_EFB_DESCRIPTION);
|
||||
AddDescription(m_disable_vram_copies, TR_DISABLE_VRAM_COPIES_DESCRIPTION);
|
||||
AddDescription(m_use_fullres_framedumps, TR_INTERNAL_RESOLUTION_FRAME_DUMPING_DESCRIPTION);
|
||||
#ifdef HAVE_FFMPEG
|
||||
AddDescription(m_dump_use_ffv1, TR_USE_FFV1_DESCRIPTION);
|
||||
#endif
|
||||
AddDescription(m_enable_cropping, TR_CROPPING_DESCRIPTION);
|
||||
AddDescription(m_enable_prog_scan, TR_PROGRESSIVE_SCAN_DESCRIPTION);
|
||||
AddDescription(m_enable_freelook, TR_FREE_LOOK_DESCRIPTION);
|
||||
#ifdef _WIN32
|
||||
AddDescription(m_borderless_fullscreen, TR_BORDERLESS_FULLSCREEN_DESCRIPTION);
|
||||
#endif
|
||||
}
|
48
Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h
Normal file
48
Source/Core/DolphinQt/Config/Graphics/AdvancedWidget.h
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWidget.h"
|
||||
|
||||
class GraphicsWindow;
|
||||
class QCheckBox;
|
||||
|
||||
class AdvancedWidget final : public GraphicsWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AdvancedWidget(GraphicsWindow* parent);
|
||||
|
||||
private:
|
||||
void LoadSettings() override;
|
||||
void SaveSettings() override;
|
||||
|
||||
void CreateWidgets();
|
||||
void ConnectWidgets();
|
||||
void AddDescriptions();
|
||||
void OnBackendChanged();
|
||||
void OnEmulationStateChanged(bool running);
|
||||
|
||||
// Debugging
|
||||
QCheckBox* m_enable_wireframe;
|
||||
QCheckBox* m_show_statistics;
|
||||
QCheckBox* m_enable_format_overlay;
|
||||
QCheckBox* m_enable_api_validation;
|
||||
|
||||
// Utility
|
||||
QCheckBox* m_dump_textures;
|
||||
QCheckBox* m_prefetch_custom_textures;
|
||||
QCheckBox* m_dump_efb_target;
|
||||
QCheckBox* m_disable_vram_copies;
|
||||
QCheckBox* m_dump_use_ffv1;
|
||||
QCheckBox* m_load_custom_textures;
|
||||
QCheckBox* m_use_fullres_framedumps;
|
||||
QCheckBox* m_enable_freelook;
|
||||
|
||||
// Misc
|
||||
QCheckBox* m_enable_cropping;
|
||||
QCheckBox* m_enable_prog_scan;
|
||||
QCheckBox* m_borderless_fullscreen;
|
||||
};
|
381
Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp
Normal file
381
Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.cpp
Normal file
@ -0,0 +1,381 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Graphics/EnhancementsWidget.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "Core/Config/GraphicsSettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsBool.h"
|
||||
#include "DolphinQt/Config/Graphics/GraphicsChoice.h"
|
||||
#include "DolphinQt/Config/Graphics/GraphicsSlider.h"
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
|
||||
#include "DolphinQt/Config/Graphics/PostProcessingConfigWindow.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
#include "UICommon/VideoUtils.h"
|
||||
|
||||
#include "VideoCommon/PostProcessing.h"
|
||||
#include "VideoCommon/VideoBackendBase.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
EnhancementsWidget::EnhancementsWidget(GraphicsWindow* parent)
|
||||
: GraphicsWidget(parent), m_block_save(false)
|
||||
{
|
||||
CreateWidgets();
|
||||
LoadSettings();
|
||||
ConnectWidgets();
|
||||
AddDescriptions();
|
||||
connect(parent, &GraphicsWindow::BackendChanged,
|
||||
[this](const QString& backend) { LoadSettings(); });
|
||||
}
|
||||
|
||||
void EnhancementsWidget::CreateWidgets()
|
||||
{
|
||||
auto* main_layout = new QVBoxLayout;
|
||||
|
||||
// Enhancements
|
||||
auto* enhancements_box = new QGroupBox(tr("Enhancements"));
|
||||
auto* enhancements_layout = new QGridLayout();
|
||||
enhancements_box->setLayout(enhancements_layout);
|
||||
|
||||
m_ir_combo = new GraphicsChoice({tr("Auto (Multiple of 640x528)"), tr("Native (640x528)"),
|
||||
tr("2x Native (1280x1056) for 720p"),
|
||||
tr("3x Native (1920x1584) for 1080p"),
|
||||
tr("4x Native (2560x2112) for 1440p"),
|
||||
tr("5x Native (3200x2640)"), tr("6x Native (3840x3168) for 4K"),
|
||||
tr("7x Native (4480x3696)"), tr("8x Native (5120x4224) for 5K")},
|
||||
Config::GFX_EFB_SCALE);
|
||||
|
||||
if (g_Config.iEFBScale > 8)
|
||||
{
|
||||
m_ir_combo->addItem(tr("Custom"));
|
||||
m_ir_combo->setCurrentIndex(m_ir_combo->count() - 1);
|
||||
}
|
||||
|
||||
m_ir_combo->setMaxVisibleItems(m_ir_combo->count());
|
||||
|
||||
m_aa_combo = new QComboBox();
|
||||
m_af_combo = new GraphicsChoice({tr("1x"), tr("2x"), tr("4x"), tr("8x"), tr("16x")},
|
||||
Config::GFX_ENHANCE_MAX_ANISOTROPY);
|
||||
|
||||
m_pp_effect = new QComboBox();
|
||||
m_configure_pp_effect = new QPushButton(tr("Configure"));
|
||||
m_scaled_efb_copy = new GraphicsBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED);
|
||||
m_per_pixel_lighting =
|
||||
new GraphicsBool(tr("Per-Pixel Lighting"), Config::GFX_ENABLE_PIXEL_LIGHTING);
|
||||
m_force_texture_filtering =
|
||||
new GraphicsBool(tr("Force Texture Filtering"), Config::GFX_ENHANCE_FORCE_FILTERING);
|
||||
m_widescreen_hack = new GraphicsBool(tr("Widescreen Hack"), Config::GFX_WIDESCREEN_HACK);
|
||||
m_disable_fog = new GraphicsBool(tr("Disable Fog"), Config::GFX_DISABLE_FOG);
|
||||
m_force_24bit_color =
|
||||
new GraphicsBool(tr("Force 24-Bit Color"), Config::GFX_ENHANCE_FORCE_TRUE_COLOR);
|
||||
m_disable_copy_filter =
|
||||
new GraphicsBool(tr("Disable Copy Filter"), Config::GFX_ENHANCE_DISABLE_COPY_FILTER);
|
||||
m_arbitrary_mipmap_detection = new GraphicsBool(tr("Arbitrary Mipmap Detection"),
|
||||
Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION);
|
||||
|
||||
enhancements_layout->addWidget(new QLabel(tr("Internal Resolution:")), 0, 0);
|
||||
enhancements_layout->addWidget(m_ir_combo, 0, 1, 1, -1);
|
||||
enhancements_layout->addWidget(new QLabel(tr("Anti-Aliasing:")), 1, 0);
|
||||
enhancements_layout->addWidget(m_aa_combo, 1, 1, 1, -1);
|
||||
enhancements_layout->addWidget(new QLabel(tr("Anisotropic Filtering:")), 2, 0);
|
||||
enhancements_layout->addWidget(m_af_combo, 2, 1, 1, -1);
|
||||
|
||||
enhancements_layout->addWidget(new QLabel(tr("Post-Processing Effect:")), 4, 0);
|
||||
enhancements_layout->addWidget(m_pp_effect, 4, 1);
|
||||
enhancements_layout->addWidget(m_configure_pp_effect, 4, 2);
|
||||
|
||||
enhancements_layout->addWidget(m_scaled_efb_copy, 5, 0);
|
||||
enhancements_layout->addWidget(m_per_pixel_lighting, 5, 1);
|
||||
enhancements_layout->addWidget(m_force_texture_filtering, 6, 0);
|
||||
enhancements_layout->addWidget(m_widescreen_hack, 6, 1);
|
||||
enhancements_layout->addWidget(m_disable_fog, 7, 0);
|
||||
enhancements_layout->addWidget(m_force_24bit_color, 7, 1);
|
||||
enhancements_layout->addWidget(m_disable_copy_filter, 8, 0);
|
||||
enhancements_layout->addWidget(m_arbitrary_mipmap_detection, 8, 1);
|
||||
|
||||
// Stereoscopy
|
||||
auto* stereoscopy_box = new QGroupBox(tr("Stereoscopy"));
|
||||
auto* stereoscopy_layout = new QGridLayout();
|
||||
stereoscopy_box->setLayout(stereoscopy_layout);
|
||||
|
||||
m_3d_mode = new GraphicsChoice(
|
||||
{tr("Off"), tr("Side-by-Side"), tr("Top-and-Bottom"), tr("Anaglyph"), tr("HDMI 3D")},
|
||||
Config::GFX_STEREO_MODE);
|
||||
m_3d_depth = new GraphicsSlider(0, 100, Config::GFX_STEREO_DEPTH);
|
||||
m_3d_convergence = new GraphicsSlider(0, 200, Config::GFX_STEREO_CONVERGENCE, 100);
|
||||
m_3d_swap_eyes = new GraphicsBool(tr("Swap Eyes"), Config::GFX_STEREO_SWAP_EYES);
|
||||
|
||||
stereoscopy_layout->addWidget(new QLabel(tr("Stereoscopic 3D Mode:")), 0, 0);
|
||||
stereoscopy_layout->addWidget(m_3d_mode, 0, 1);
|
||||
stereoscopy_layout->addWidget(new QLabel(tr("Depth:")), 1, 0);
|
||||
stereoscopy_layout->addWidget(m_3d_depth, 1, 1);
|
||||
stereoscopy_layout->addWidget(new QLabel(tr("Convergence:")), 2, 0);
|
||||
stereoscopy_layout->addWidget(m_3d_convergence, 2, 1);
|
||||
stereoscopy_layout->addWidget(m_3d_swap_eyes, 3, 0);
|
||||
|
||||
main_layout->addWidget(enhancements_box);
|
||||
main_layout->addWidget(stereoscopy_box);
|
||||
main_layout->addStretch();
|
||||
|
||||
setLayout(main_layout);
|
||||
}
|
||||
|
||||
void EnhancementsWidget::ConnectWidgets()
|
||||
{
|
||||
connect(m_aa_combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
[this](int) { SaveSettings(); });
|
||||
connect(m_pp_effect, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
[this](int) { SaveSettings(); });
|
||||
connect(m_3d_mode, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
[this] {
|
||||
m_block_save = true;
|
||||
LoadPPShaders();
|
||||
m_block_save = false;
|
||||
|
||||
SaveSettings();
|
||||
});
|
||||
connect(m_configure_pp_effect, &QPushButton::pressed, this,
|
||||
&EnhancementsWidget::ConfigurePostProcessingShader);
|
||||
}
|
||||
|
||||
void EnhancementsWidget::LoadPPShaders()
|
||||
{
|
||||
const bool anaglyph = g_Config.stereo_mode == StereoMode::Anaglyph;
|
||||
std::vector<std::string> shaders =
|
||||
g_Config.stereo_mode == StereoMode::Anaglyph ?
|
||||
PostProcessingShaderImplementation::GetAnaglyphShaderList(
|
||||
g_Config.backend_info.api_type) :
|
||||
PostProcessingShaderImplementation::GetShaderList(g_Config.backend_info.api_type);
|
||||
|
||||
m_pp_effect->clear();
|
||||
|
||||
if (!anaglyph)
|
||||
m_pp_effect->addItem(tr("(off)"));
|
||||
|
||||
auto selected_shader = Config::Get(Config::GFX_ENHANCE_POST_SHADER);
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (const auto& shader : shaders)
|
||||
{
|
||||
m_pp_effect->addItem(QString::fromStdString(shader));
|
||||
if (selected_shader == shader)
|
||||
{
|
||||
m_pp_effect->setCurrentIndex(m_pp_effect->count() - 1);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (anaglyph && !found)
|
||||
m_pp_effect->setCurrentIndex(m_pp_effect->findText(QStringLiteral("dubois")));
|
||||
|
||||
const bool supports_postprocessing = g_Config.backend_info.bSupportsPostProcessing;
|
||||
m_pp_effect->setEnabled(supports_postprocessing);
|
||||
|
||||
m_pp_effect->setToolTip(supports_postprocessing ?
|
||||
QStringLiteral("") :
|
||||
tr("%1 doesn't support this feature.")
|
||||
.arg(tr(g_video_backend->GetDisplayName().c_str())));
|
||||
|
||||
PostProcessingShaderConfiguration pp_shader;
|
||||
if (selected_shader != "(off)" && supports_postprocessing)
|
||||
{
|
||||
pp_shader.LoadShader(selected_shader);
|
||||
m_configure_pp_effect->setEnabled(pp_shader.HasOptions());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_configure_pp_effect->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void EnhancementsWidget::LoadSettings()
|
||||
{
|
||||
m_block_save = true;
|
||||
// Anti-Aliasing
|
||||
|
||||
int aa_selection = Config::Get(Config::GFX_MSAA);
|
||||
bool ssaa = Config::Get(Config::GFX_SSAA);
|
||||
|
||||
m_aa_combo->clear();
|
||||
for (const auto& option : VideoUtils::GetAvailableAntialiasingModes(m_msaa_modes))
|
||||
m_aa_combo->addItem(option == "None" ? tr("None") : QString::fromStdString(option));
|
||||
|
||||
m_aa_combo->setCurrentText(
|
||||
QString::fromStdString(std::to_string(aa_selection) + "x " + (ssaa ? "SSAA" : "MSAA")));
|
||||
m_aa_combo->setEnabled(m_aa_combo->count() > 1);
|
||||
|
||||
// Post Processing Shader
|
||||
LoadPPShaders();
|
||||
|
||||
// Stereoscopy
|
||||
bool supports_stereoscopy = g_Config.backend_info.bSupportsGeometryShaders;
|
||||
bool supports_3dvision = g_Config.backend_info.bSupports3DVision;
|
||||
|
||||
bool has_3dvision = m_3d_mode->count() == 6;
|
||||
|
||||
if (has_3dvision && !supports_3dvision)
|
||||
m_3d_mode->removeItem(5);
|
||||
|
||||
if (!has_3dvision && supports_3dvision)
|
||||
m_3d_mode->addItem(tr("NVIDIA 3D Vision"));
|
||||
|
||||
m_3d_mode->setEnabled(supports_stereoscopy);
|
||||
m_3d_convergence->setEnabled(supports_stereoscopy);
|
||||
m_3d_depth->setEnabled(supports_stereoscopy);
|
||||
m_3d_swap_eyes->setEnabled(supports_stereoscopy);
|
||||
m_block_save = false;
|
||||
}
|
||||
|
||||
void EnhancementsWidget::SaveSettings()
|
||||
{
|
||||
if (m_block_save)
|
||||
return;
|
||||
|
||||
bool is_ssaa = m_aa_combo->currentText().endsWith(QStringLiteral("SSAA"));
|
||||
|
||||
int aa_value = m_aa_combo->currentIndex();
|
||||
|
||||
if (aa_value == 0)
|
||||
{
|
||||
aa_value = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aa_value > m_msaa_modes)
|
||||
aa_value -= m_msaa_modes;
|
||||
aa_value = std::pow(2, aa_value);
|
||||
}
|
||||
Config::SetBaseOrCurrent(Config::GFX_MSAA, static_cast<unsigned int>(aa_value));
|
||||
|
||||
Config::SetBaseOrCurrent(Config::GFX_SSAA, is_ssaa);
|
||||
|
||||
Config::SetBaseOrCurrent(
|
||||
Config::GFX_ENHANCE_POST_SHADER,
|
||||
m_pp_effect->currentIndex() == 0 ? "(off)" : m_pp_effect->currentText().toStdString());
|
||||
|
||||
PostProcessingShaderConfiguration pp_shader;
|
||||
if (Config::Get(Config::GFX_ENHANCE_POST_SHADER) != "(off)")
|
||||
{
|
||||
pp_shader.LoadShader(Config::Get(Config::GFX_ENHANCE_POST_SHADER));
|
||||
m_configure_pp_effect->setEnabled(pp_shader.HasOptions());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_configure_pp_effect->setEnabled(false);
|
||||
}
|
||||
|
||||
LoadSettings();
|
||||
}
|
||||
|
||||
void EnhancementsWidget::AddDescriptions()
|
||||
{
|
||||
static const char TR_INTERNAL_RESOLUTION_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Specifies the resolution used to render at. A high resolution greatly improves "
|
||||
"visual quality, but also greatly increases GPU load and can cause issues in "
|
||||
"certain games. Generally speaking, the lower the internal resolution is, the "
|
||||
"better your performance will be.\n\nIf unsure, select Native.");
|
||||
|
||||
static const char TR_ANTIALIAS_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Reduces the amount of aliasing caused by rasterizing 3D graphics. This smooths "
|
||||
"out jagged edges on objects.\nIncreases GPU load and sometimes causes graphical "
|
||||
"issues. SSAA is significantly more demanding than MSAA, but provides top quality "
|
||||
"geometry anti-aliasing and also applies anti-aliasing to lighting, shader "
|
||||
"effects, and textures.\n\nIf unsure, select None.");
|
||||
|
||||
static const char TR_ANISOTROPIC_FILTERING_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Enable anisotropic filtering.\nEnhances visual quality of textures that are at oblique "
|
||||
"viewing angles.\nMight cause issues in a small number of games.\n\nIf unsure, select 1x.");
|
||||
|
||||
static const char TR_POSTPROCESSING_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Apply a post-processing effect after finishing a frame.\n\nIf unsure, select (off).");
|
||||
|
||||
static const char TR_SCALED_EFB_COPY_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Greatly increases quality of textures generated using render-to-texture "
|
||||
"effects.\nRaising the "
|
||||
"internal resolution will improve the effect of this setting.\nSlightly increases GPU "
|
||||
"load and "
|
||||
"causes relatively few graphical issues.\n\nIf unsure, leave this checked.");
|
||||
static const char TR_PER_PIXEL_LIGHTING_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Calculates lighting of 3D objects per-pixel rather than per-vertex, smoothing out the "
|
||||
"appearance of lit polygons and making individual triangles less noticeable.\nRarely causes "
|
||||
"slowdowns or graphical issues.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_WIDESCREEN_HACK_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Forces the game to output graphics for any aspect ratio.\nUse with \"Aspect Ratio\" set to "
|
||||
"\"Force 16:9\" to force 4:3-only games to run at 16:9.\nRarely produces good results and "
|
||||
"often partially breaks graphics and game UIs.\nUnnecessary (and detrimental) if using any "
|
||||
"AR/Gecko-code widescreen patches.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_REMOVE_FOG_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Makes distant objects more visible by removing fog, thus increasing the overall "
|
||||
"detail.\nDisabling fog will break some games which rely on proper fog "
|
||||
"emulation.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_3D_MODE_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Selects the stereoscopic 3D mode. Stereoscopy allows you to get a better feeling "
|
||||
"of depth if you have the necessary hardware.\nSide-by-Side and Top-and-Bottom are "
|
||||
"used by most 3D TVs.\nAnaglyph is used for Red-Cyan colored glasses.\nHDMI 3D is "
|
||||
"used when your monitor supports 3D display resolutions.\nHeavily decreases "
|
||||
"emulation speed and sometimes causes issues.\n\nIf unsure, select Off.");
|
||||
static const char TR_3D_DEPTH_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Controls the separation distance between the virtual cameras.\nA higher value "
|
||||
"creates a stronger feeling of depth while a lower value is more comfortable.");
|
||||
static const char TR_3D_CONVERGENCE_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Controls the distance of the convergence plane. This is the distance at which "
|
||||
"virtual objects will appear to be in front of the screen.\nA higher value creates "
|
||||
"stronger out-of-screen effects while a lower value is more comfortable.");
|
||||
static const char TR_3D_SWAP_EYES_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Swaps the left and right eye. Mostly useful if you want to view side-by-side "
|
||||
"cross-eyed.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_FORCE_24BIT_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Forces the game to render the RGB color channels in 24-bit, thereby increasing "
|
||||
"quality by reducing color banding.\nIt has no impact on performance and causes "
|
||||
"few graphical issues.\n\nIf unsure, leave this checked.");
|
||||
static const char TR_FORCE_TEXTURE_FILTERING_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Filter all textures, including any that the game explicitly set as "
|
||||
"unfiltered.\nMay improve quality of certain textures in some games, but will "
|
||||
"cause issues in others.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_DISABLE_COPY_FILTER_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Disables the blending of adjacent rows when copying the EFB. This is known in "
|
||||
"some games as \"deflickering\" or \"smoothing\". Disabling the filter has no "
|
||||
"effect on performance, but may result in a sharper image, and causes few "
|
||||
"graphical issues.\n\nIf unsure, leave this checked.");
|
||||
static const char TR_ARBITRARY_MIPMAP_DETECTION_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Enables detection of arbitrary mipmaps, which some games use for special distance-based "
|
||||
"effects. May have false positives that result in blurry textures at increased internal "
|
||||
"resolution, such as in games that use very low resolution mipmaps.\nDisabling this can also "
|
||||
"reduce stutter in games that frequently load new textures.\nThis feature is not compatible "
|
||||
"with GPU Texture Decoding.\n\nIf unsure, leave this checked.");
|
||||
|
||||
AddDescription(m_ir_combo, TR_INTERNAL_RESOLUTION_DESCRIPTION);
|
||||
AddDescription(m_aa_combo, TR_ANTIALIAS_DESCRIPTION);
|
||||
AddDescription(m_af_combo, TR_ANISOTROPIC_FILTERING_DESCRIPTION);
|
||||
AddDescription(m_pp_effect, TR_POSTPROCESSING_DESCRIPTION);
|
||||
AddDescription(m_scaled_efb_copy, TR_SCALED_EFB_COPY_DESCRIPTION);
|
||||
AddDescription(m_per_pixel_lighting, TR_PER_PIXEL_LIGHTING_DESCRIPTION);
|
||||
AddDescription(m_widescreen_hack, TR_WIDESCREEN_HACK_DESCRIPTION);
|
||||
AddDescription(m_disable_fog, TR_REMOVE_FOG_DESCRIPTION);
|
||||
AddDescription(m_force_24bit_color, TR_FORCE_24BIT_DESCRIPTION);
|
||||
AddDescription(m_force_texture_filtering, TR_FORCE_TEXTURE_FILTERING_DESCRIPTION);
|
||||
AddDescription(m_disable_copy_filter, TR_DISABLE_COPY_FILTER_DESCRIPTION);
|
||||
AddDescription(m_arbitrary_mipmap_detection, TR_ARBITRARY_MIPMAP_DETECTION_DESCRIPTION);
|
||||
AddDescription(m_3d_mode, TR_3D_MODE_DESCRIPTION);
|
||||
AddDescription(m_3d_depth, TR_3D_DEPTH_DESCRIPTION);
|
||||
AddDescription(m_3d_convergence, TR_3D_CONVERGENCE_DESCRIPTION);
|
||||
AddDescription(m_3d_swap_eyes, TR_3D_SWAP_EYES_DESCRIPTION);
|
||||
}
|
||||
|
||||
void EnhancementsWidget::ConfigurePostProcessingShader()
|
||||
{
|
||||
const std::string shader = Config::Get(Config::GFX_ENHANCE_POST_SHADER);
|
||||
PostProcessingConfigWindow(this, shader).exec();
|
||||
}
|
54
Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h
Normal file
54
Source/Core/DolphinQt/Config/Graphics/EnhancementsWidget.h
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWidget.h"
|
||||
|
||||
class GraphicsWindow;
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QPushButton;
|
||||
class QSlider;
|
||||
|
||||
class EnhancementsWidget final : public GraphicsWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit EnhancementsWidget(GraphicsWindow* parent);
|
||||
|
||||
private:
|
||||
void LoadSettings() override;
|
||||
void SaveSettings() override;
|
||||
|
||||
void CreateWidgets();
|
||||
void ConnectWidgets();
|
||||
void AddDescriptions();
|
||||
void ConfigurePostProcessingShader();
|
||||
void LoadPPShaders();
|
||||
|
||||
// Enhancements
|
||||
QComboBox* m_ir_combo;
|
||||
QComboBox* m_aa_combo;
|
||||
QComboBox* m_af_combo;
|
||||
QComboBox* m_pp_effect;
|
||||
QPushButton* m_configure_pp_effect;
|
||||
QCheckBox* m_scaled_efb_copy;
|
||||
QCheckBox* m_per_pixel_lighting;
|
||||
QCheckBox* m_force_texture_filtering;
|
||||
QCheckBox* m_widescreen_hack;
|
||||
QCheckBox* m_disable_fog;
|
||||
QCheckBox* m_force_24bit_color;
|
||||
QCheckBox* m_disable_copy_filter;
|
||||
QCheckBox* m_arbitrary_mipmap_detection;
|
||||
|
||||
// Stereoscopy
|
||||
QComboBox* m_3d_mode;
|
||||
QSlider* m_3d_depth;
|
||||
QSlider* m_3d_convergence;
|
||||
QCheckBox* m_3d_swap_eyes;
|
||||
|
||||
int m_msaa_modes;
|
||||
bool m_block_save;
|
||||
};
|
322
Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp
Normal file
322
Source/Core/DolphinQt/Config/Graphics/GeneralWidget.cpp
Normal file
@ -0,0 +1,322 @@
|
||||
// Copyright 2017 Dolphin Emulator Project5~5~5~
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GeneralWidget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
#include <QRadioButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "Core/Config/GraphicsSettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsBool.h"
|
||||
#include "DolphinQt/Config/Graphics/GraphicsChoice.h"
|
||||
#include "DolphinQt/Config/Graphics/GraphicsRadio.h"
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
#include "UICommon/VideoUtils.h"
|
||||
|
||||
#include "VideoCommon/VideoBackendBase.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
GeneralWidget::GeneralWidget(X11Utils::XRRConfiguration* xrr_config, GraphicsWindow* parent)
|
||||
: GraphicsWidget(parent), m_xrr_config(xrr_config)
|
||||
{
|
||||
CreateWidgets();
|
||||
LoadSettings();
|
||||
ConnectWidgets();
|
||||
AddDescriptions();
|
||||
emit BackendChanged(QString::fromStdString(SConfig::GetInstance().m_strVideoBackend));
|
||||
|
||||
connect(parent, &GraphicsWindow::BackendChanged, this, &GeneralWidget::OnBackendChanged);
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||
[=](Core::State state) { OnEmulationStateChanged(state != Core::State::Uninitialized); });
|
||||
}
|
||||
|
||||
void GeneralWidget::CreateWidgets()
|
||||
{
|
||||
auto* main_layout = new QVBoxLayout;
|
||||
|
||||
// Basic Section
|
||||
auto* m_video_box = new QGroupBox(tr("Basic"));
|
||||
m_video_layout = new QGridLayout();
|
||||
|
||||
m_backend_combo = new QComboBox();
|
||||
m_aspect_combo =
|
||||
new GraphicsChoice({tr("Auto"), tr("Force 16:9"), tr("Force 4:3"), tr("Stretch to Window")},
|
||||
Config::GFX_ASPECT_RATIO);
|
||||
m_adapter_combo = new QComboBox;
|
||||
m_enable_vsync = new GraphicsBool(tr("V-Sync"), Config::GFX_VSYNC);
|
||||
m_enable_fullscreen = new QCheckBox(tr("Use Fullscreen"));
|
||||
|
||||
m_video_box->setLayout(m_video_layout);
|
||||
|
||||
for (auto& backend : g_available_video_backends)
|
||||
m_backend_combo->addItem(tr(backend->GetDisplayName().c_str()),
|
||||
QVariant(QString::fromStdString(backend->GetName())));
|
||||
|
||||
m_video_layout->addWidget(new QLabel(tr("Backend:")), 0, 0);
|
||||
m_video_layout->addWidget(m_backend_combo, 0, 1);
|
||||
|
||||
m_video_layout->addWidget(new QLabel(tr("Adapter:")), 1, 0);
|
||||
m_video_layout->addWidget(m_adapter_combo, 1, 1);
|
||||
|
||||
m_video_layout->addWidget(new QLabel(tr("Aspect Ratio:")), 3, 0);
|
||||
m_video_layout->addWidget(m_aspect_combo, 3, 1);
|
||||
|
||||
m_video_layout->addWidget(m_enable_vsync, 4, 0);
|
||||
m_video_layout->addWidget(m_enable_fullscreen, 4, 1);
|
||||
|
||||
// Other
|
||||
auto* m_options_box = new QGroupBox(tr("Other"));
|
||||
auto* m_options_layout = new QGridLayout();
|
||||
|
||||
m_show_fps = new GraphicsBool(tr("Show FPS"), Config::GFX_SHOW_FPS);
|
||||
m_show_ping = new GraphicsBool(tr("Show NetPlay Ping"), Config::GFX_SHOW_NETPLAY_PING);
|
||||
m_log_render_time =
|
||||
new GraphicsBool(tr("Log Render Time to File"), Config::GFX_LOG_RENDER_TIME_TO_FILE);
|
||||
m_autoadjust_window_size = new QCheckBox(tr("Auto-Adjust Window Size"));
|
||||
m_show_messages =
|
||||
new GraphicsBool(tr("Show NetPlay Messages"), Config::GFX_SHOW_NETPLAY_MESSAGES);
|
||||
m_render_main_window = new QCheckBox(tr("Render to Main Window"));
|
||||
|
||||
m_options_box->setLayout(m_options_layout);
|
||||
|
||||
m_options_layout->addWidget(m_show_fps, 0, 0);
|
||||
m_options_layout->addWidget(m_show_ping, 0, 1);
|
||||
|
||||
m_options_layout->addWidget(m_log_render_time, 1, 0);
|
||||
m_options_layout->addWidget(m_autoadjust_window_size, 1, 1);
|
||||
|
||||
m_options_layout->addWidget(m_show_messages, 2, 0);
|
||||
m_options_layout->addWidget(m_render_main_window, 2, 1);
|
||||
|
||||
// Other
|
||||
auto* shader_compilation_box = new QGroupBox(tr("Shader Compilation"));
|
||||
auto* shader_compilation_layout = new QGridLayout();
|
||||
|
||||
const std::array<const char*, 4> modes = {{
|
||||
"Synchronous",
|
||||
"Synchronous (Ubershaders)",
|
||||
"Asynchronous (Ubershaders)",
|
||||
"Asynchronous (Skip Drawing)",
|
||||
}};
|
||||
for (size_t i = 0; i < modes.size(); i++)
|
||||
{
|
||||
m_shader_compilation_mode[i] = new GraphicsRadioInt(
|
||||
tr(modes[i]), Config::GFX_SHADER_COMPILATION_MODE, static_cast<int>(i));
|
||||
shader_compilation_layout->addWidget(m_shader_compilation_mode[i], static_cast<int>(i / 2),
|
||||
static_cast<int>(i % 2));
|
||||
}
|
||||
m_wait_for_shaders = new GraphicsBool(tr("Compile Shaders Before Starting"),
|
||||
Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING);
|
||||
shader_compilation_layout->addWidget(m_wait_for_shaders);
|
||||
shader_compilation_box->setLayout(shader_compilation_layout);
|
||||
|
||||
main_layout->addWidget(m_video_box);
|
||||
main_layout->addWidget(m_options_box);
|
||||
main_layout->addWidget(shader_compilation_box);
|
||||
main_layout->addStretch();
|
||||
|
||||
setLayout(main_layout);
|
||||
}
|
||||
|
||||
void GeneralWidget::ConnectWidgets()
|
||||
{
|
||||
// Video Backend
|
||||
connect(m_backend_combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this, &GeneralWidget::SaveSettings);
|
||||
connect(m_adapter_combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this, [](int index) {
|
||||
g_Config.iAdapter = index;
|
||||
Config::SetBaseOrCurrent(Config::GFX_ADAPTER, index);
|
||||
});
|
||||
|
||||
for (QCheckBox* checkbox : {m_enable_fullscreen, m_render_main_window, m_autoadjust_window_size})
|
||||
connect(checkbox, &QCheckBox::toggled, this, &GeneralWidget::SaveSettings);
|
||||
}
|
||||
|
||||
void GeneralWidget::LoadSettings()
|
||||
{
|
||||
// Video Backend
|
||||
m_backend_combo->setCurrentIndex(m_backend_combo->findData(
|
||||
QVariant(QString::fromStdString(SConfig::GetInstance().m_strVideoBackend))));
|
||||
|
||||
// Enable Fullscreen
|
||||
m_enable_fullscreen->setChecked(SConfig::GetInstance().bFullscreen);
|
||||
|
||||
// Render to Main Window
|
||||
m_render_main_window->setChecked(SConfig::GetInstance().bRenderToMain);
|
||||
|
||||
// Autoadjust window size
|
||||
m_autoadjust_window_size->setChecked(SConfig::GetInstance().bRenderWindowAutoSize);
|
||||
}
|
||||
|
||||
void GeneralWidget::SaveSettings()
|
||||
{
|
||||
// Video Backend
|
||||
const auto current_backend = m_backend_combo->currentData().toString().toStdString();
|
||||
if (SConfig::GetInstance().m_strVideoBackend != current_backend)
|
||||
{
|
||||
if (current_backend == "Software Renderer")
|
||||
{
|
||||
QMessageBox confirm_sw(this);
|
||||
|
||||
confirm_sw.setIcon(QMessageBox::Warning);
|
||||
confirm_sw.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
confirm_sw.setWindowTitle(tr("Confirm backend change"));
|
||||
confirm_sw.setText(tr("Software rendering is an order of magnitude slower than using the "
|
||||
"other backends.\nIt's only useful for debugging purposes.\nDo you "
|
||||
"really want to enable software rendering? If unsure, select 'No'."));
|
||||
|
||||
if (confirm_sw.exec() != QMessageBox::Yes)
|
||||
{
|
||||
m_backend_combo->setCurrentIndex(m_backend_combo->findData(
|
||||
QVariant(QString::fromStdString(SConfig::GetInstance().m_strVideoBackend))));
|
||||
return;
|
||||
}
|
||||
}
|
||||
emit BackendChanged(QString::fromStdString(current_backend));
|
||||
}
|
||||
|
||||
// Enable Fullscreen
|
||||
SConfig::GetInstance().bFullscreen = m_enable_fullscreen->isChecked();
|
||||
// Autoadjust window size
|
||||
SConfig::GetInstance().bRenderWindowAutoSize = m_autoadjust_window_size->isChecked();
|
||||
// Render To Main
|
||||
SConfig::GetInstance().bRenderToMain = m_render_main_window->isChecked();
|
||||
}
|
||||
|
||||
void GeneralWidget::OnEmulationStateChanged(bool running)
|
||||
{
|
||||
m_backend_combo->setEnabled(!running);
|
||||
m_render_main_window->setEnabled(!running);
|
||||
|
||||
m_adapter_combo->setEnabled(!running);
|
||||
}
|
||||
|
||||
void GeneralWidget::AddDescriptions()
|
||||
{
|
||||
// We need QObject::tr
|
||||
#if defined(_WIN32)
|
||||
static const char TR_BACKEND_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Selects which graphics API to use internally.\n\nThe software renderer is extremely "
|
||||
"slow and only useful for debugging, so you will want to use either OpenGL, Direct3D, "
|
||||
"or Vulkan. Different games and different GPUs will behave differently on each "
|
||||
"backend, so for the best emulation experience it is recommended to try each and "
|
||||
"select the backend that is least problematic.\n\nIf unsure, select OpenGL.");
|
||||
#else
|
||||
static const char TR_BACKEND_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Selects what graphics API to use internally.\nThe software renderer is extremely "
|
||||
"slow and only useful for debugging, so unless you have a reason to use it you'll "
|
||||
"want to select OpenGL here.\n\nIf unsure, select OpenGL.");
|
||||
#endif
|
||||
static const char TR_ADAPTER_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Selects a hardware adapter to use.\n\nIf unsure, use the first one.");
|
||||
static const char TR_FULLSCREEN_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Enable this if you want the whole screen to be used for rendering.\nIf this is disabled, a "
|
||||
"render window will be created instead.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_AUTOSIZE_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Automatically adjusts the window size to your internal resolution.\n\nIf unsure, "
|
||||
"leave this unchecked.");
|
||||
|
||||
static const char TR_RENDER_TO_MAINWINDOW_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Enable this if you want to use the main Dolphin window for rendering rather than "
|
||||
"a separate render window.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_ASPECT_RATIO_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Select what aspect ratio to use when rendering:\nAuto: Use the native aspect "
|
||||
"ratio\nForce 16:9: Mimic an analog TV with a widescreen aspect ratio.\nForce 4:3: "
|
||||
"Mimic a standard 4:3 analog TV.\nStretch to Window: Stretch the picture to the "
|
||||
"window size.\n\nIf unsure, select Auto.");
|
||||
static const char TR_VSYNC_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Wait for vertical blanks in order to reduce tearing.\nDecreases performance if "
|
||||
"emulation speed is below 100%.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_SHOW_FPS_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Show the number of frames rendered per second as a measure of "
|
||||
"emulation speed.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_SHOW_NETPLAY_PING_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Show the players' maximum Ping while playing on "
|
||||
"NetPlay.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_LOG_RENDERTIME_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Log the render time of every frame to User/Logs/render_time.txt. Use this "
|
||||
"feature when you want to measure the performance of Dolphin.\n\nIf "
|
||||
"unsure, leave this unchecked.");
|
||||
static const char TR_SHOW_NETPLAY_MESSAGES_DESCRIPTION[] =
|
||||
QT_TR_NOOP("When playing on NetPlay, show chat messages, buffer changes and "
|
||||
"desync alerts.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_SHADER_COMPILE_SYNC_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Ubershaders are never used. Stuttering will occur during shader "
|
||||
"compilation, but GPU demands are low. Recommended for low-end hardware.\n\nIf "
|
||||
"unsure, select this mode.");
|
||||
static const char TR_SHADER_COMPILE_UBER_ONLY_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Ubershaders will always be used. Provides a near stutter-free experience at the cost of "
|
||||
"high GPU performance requirements. Only recommended for high-end systems.");
|
||||
static const char TR_SHADER_COMPILE_ASYNC_UBER_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Ubershaders will be used to prevent stuttering during shader compilation, but "
|
||||
"specialized shaders will be used when they will not cause stuttering. In the "
|
||||
"best case it eliminates shader compilation stuttering while having minimal "
|
||||
"performance impact, but results depend on video driver behavior.");
|
||||
static const char TR_SHADER_COMPILE_ASYNC_SKIP_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Prevents shader compilation stuttering by not rendering waiting objects. Can work in "
|
||||
"scenarios where Ubershaders doesn't, at the cost of introducing visual glitches and broken "
|
||||
"effects. Not recommended, only use if the other options give poor results on your system.");
|
||||
static const char TR_SHADER_COMPILE_BEFORE_START_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Waits for all shaders to finish compiling before starting a game. Enabling this "
|
||||
"option may reduce stuttering or hitching for a short time after the game is "
|
||||
"started, at the cost of a longer delay before the game starts. For systems with "
|
||||
"two or fewer cores, it is recommended to enable this option, as a large shader "
|
||||
"queue may reduce frame rates. Otherwise, if unsure, leave this unchecked.");
|
||||
|
||||
AddDescription(m_backend_combo, TR_BACKEND_DESCRIPTION);
|
||||
AddDescription(m_adapter_combo, TR_ADAPTER_DESCRIPTION);
|
||||
AddDescription(m_aspect_combo, TR_ASPECT_RATIO_DESCRIPTION);
|
||||
AddDescription(m_enable_vsync, TR_VSYNC_DESCRIPTION);
|
||||
AddDescription(m_enable_fullscreen, TR_FULLSCREEN_DESCRIPTION);
|
||||
AddDescription(m_show_fps, TR_SHOW_FPS_DESCRIPTION);
|
||||
AddDescription(m_show_ping, TR_SHOW_NETPLAY_PING_DESCRIPTION);
|
||||
AddDescription(m_log_render_time, TR_LOG_RENDERTIME_DESCRIPTION);
|
||||
AddDescription(m_autoadjust_window_size, TR_AUTOSIZE_DESCRIPTION);
|
||||
AddDescription(m_show_messages, TR_SHOW_NETPLAY_MESSAGES_DESCRIPTION);
|
||||
AddDescription(m_render_main_window, TR_RENDER_TO_MAINWINDOW_DESCRIPTION);
|
||||
AddDescription(m_shader_compilation_mode[0], TR_SHADER_COMPILE_SYNC_DESCRIPTION);
|
||||
AddDescription(m_shader_compilation_mode[1], TR_SHADER_COMPILE_UBER_ONLY_DESCRIPTION);
|
||||
AddDescription(m_shader_compilation_mode[2], TR_SHADER_COMPILE_ASYNC_UBER_DESCRIPTION);
|
||||
AddDescription(m_shader_compilation_mode[3], TR_SHADER_COMPILE_ASYNC_SKIP_DESCRIPTION);
|
||||
AddDescription(m_wait_for_shaders, TR_SHADER_COMPILE_BEFORE_START_DESCRIPTION);
|
||||
}
|
||||
|
||||
void GeneralWidget::OnBackendChanged(const QString& backend_name)
|
||||
{
|
||||
m_backend_combo->setCurrentIndex(m_backend_combo->findData(QVariant(backend_name)));
|
||||
|
||||
const bool old = m_adapter_combo->blockSignals(true);
|
||||
|
||||
m_adapter_combo->clear();
|
||||
|
||||
const auto& adapters = g_Config.backend_info.Adapters;
|
||||
|
||||
for (const auto& adapter : adapters)
|
||||
m_adapter_combo->addItem(QString::fromStdString(adapter));
|
||||
|
||||
const bool supports_adapters = !adapters.empty();
|
||||
|
||||
m_adapter_combo->setCurrentIndex(g_Config.iAdapter);
|
||||
m_adapter_combo->setEnabled(supports_adapters);
|
||||
|
||||
m_adapter_combo->setToolTip(supports_adapters ?
|
||||
QStringLiteral("") :
|
||||
tr("%1 doesn't support this feature.")
|
||||
.arg(tr(g_video_backend->GetDisplayName().c_str())));
|
||||
|
||||
m_adapter_combo->blockSignals(old);
|
||||
}
|
59
Source/Core/DolphinQt/Config/Graphics/GeneralWidget.h
Normal file
59
Source/Core/DolphinQt/Config/Graphics/GeneralWidget.h
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWidget.h"
|
||||
|
||||
class GraphicsWindow;
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QRadioButton;
|
||||
class QGridLayout;
|
||||
|
||||
namespace X11Utils
|
||||
{
|
||||
class XRRConfiguration;
|
||||
}
|
||||
|
||||
class GeneralWidget final : public GraphicsWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GeneralWidget(X11Utils::XRRConfiguration* xrr_config, GraphicsWindow* parent);
|
||||
signals:
|
||||
void BackendChanged(const QString& backend);
|
||||
|
||||
private:
|
||||
void LoadSettings() override;
|
||||
void SaveSettings() override;
|
||||
|
||||
void CreateWidgets();
|
||||
void ConnectWidgets();
|
||||
void AddDescriptions();
|
||||
|
||||
void OnBackendChanged(const QString& backend_name);
|
||||
void OnEmulationStateChanged(bool running);
|
||||
|
||||
// Video
|
||||
QGridLayout* m_video_layout;
|
||||
QComboBox* m_backend_combo;
|
||||
QComboBox* m_adapter_combo;
|
||||
QComboBox* m_aspect_combo;
|
||||
QCheckBox* m_enable_vsync;
|
||||
QCheckBox* m_enable_fullscreen;
|
||||
|
||||
// Options
|
||||
QCheckBox* m_show_fps;
|
||||
QCheckBox* m_show_ping;
|
||||
QCheckBox* m_log_render_time;
|
||||
QCheckBox* m_autoadjust_window_size;
|
||||
QCheckBox* m_show_messages;
|
||||
QCheckBox* m_render_main_window;
|
||||
std::array<QRadioButton*, 4> m_shader_compilation_mode{};
|
||||
QCheckBox* m_wait_for_shaders;
|
||||
|
||||
X11Utils::XRRConfiguration* m_xrr_config;
|
||||
};
|
54
Source/Core/DolphinQt/Config/Graphics/GraphicsBool.cpp
Normal file
54
Source/Core/DolphinQt/Config/Graphics/GraphicsBool.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsBool.h"
|
||||
|
||||
#include "Common/Config/Config.h"
|
||||
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
#include <QFont>
|
||||
|
||||
GraphicsBool::GraphicsBool(const QString& label, const Config::ConfigInfo<bool>& setting,
|
||||
bool reverse)
|
||||
: QCheckBox(label), m_setting(setting), m_reverse(reverse)
|
||||
{
|
||||
connect(this, &QCheckBox::toggled, this, &GraphicsBool::Update);
|
||||
setChecked(Config::Get(m_setting) ^ reverse);
|
||||
|
||||
connect(&Settings::Instance(), &Settings::ConfigChanged, [this] {
|
||||
QFont bf = font();
|
||||
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
|
||||
setFont(bf);
|
||||
|
||||
bool old = blockSignals(true);
|
||||
setChecked(Config::Get(m_setting) ^ m_reverse);
|
||||
blockSignals(old);
|
||||
});
|
||||
}
|
||||
|
||||
void GraphicsBool::Update()
|
||||
{
|
||||
Config::SetBaseOrCurrent(m_setting, static_cast<bool>(isChecked() ^ m_reverse));
|
||||
}
|
||||
|
||||
GraphicsBoolEx::GraphicsBoolEx(const QString& label, const Config::ConfigInfo<bool>& setting,
|
||||
bool reverse)
|
||||
: QRadioButton(label), m_setting(setting), m_reverse(reverse)
|
||||
{
|
||||
connect(this, &QCheckBox::toggled, this, &GraphicsBoolEx::Update);
|
||||
setChecked(Config::Get(m_setting) ^ reverse);
|
||||
|
||||
if (Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base)
|
||||
{
|
||||
QFont bf = font();
|
||||
bf.setBold(true);
|
||||
setFont(bf);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsBoolEx::Update()
|
||||
{
|
||||
Config::SetBaseOrCurrent(m_setting, static_cast<bool>(isChecked() ^ m_reverse));
|
||||
}
|
41
Source/Core/DolphinQt/Config/Graphics/GraphicsBool.h
Normal file
41
Source/Core/DolphinQt/Config/Graphics/GraphicsBool.h
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QRadioButton>
|
||||
|
||||
namespace Config
|
||||
{
|
||||
template <typename T>
|
||||
struct ConfigInfo;
|
||||
}
|
||||
|
||||
class GraphicsBool : public QCheckBox
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GraphicsBool(const QString& label, const Config::ConfigInfo<bool>& setting, bool reverse = false);
|
||||
|
||||
private:
|
||||
void Update();
|
||||
|
||||
const Config::ConfigInfo<bool>& m_setting;
|
||||
bool m_reverse;
|
||||
};
|
||||
|
||||
class GraphicsBoolEx : public QRadioButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GraphicsBoolEx(const QString& label, const Config::ConfigInfo<bool>& setting,
|
||||
bool reverse = false);
|
||||
|
||||
private:
|
||||
void Update();
|
||||
|
||||
const Config::ConfigInfo<bool>& m_setting;
|
||||
bool m_reverse;
|
||||
};
|
33
Source/Core/DolphinQt/Config/Graphics/GraphicsChoice.cpp
Normal file
33
Source/Core/DolphinQt/Config/Graphics/GraphicsChoice.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsChoice.h"
|
||||
|
||||
#include "Common/Config/Config.h"
|
||||
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
GraphicsChoice::GraphicsChoice(const QStringList& options, const Config::ConfigInfo<int>& setting)
|
||||
: m_setting(setting)
|
||||
{
|
||||
addItems(options);
|
||||
connect(this, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
||||
&GraphicsChoice::Update);
|
||||
setCurrentIndex(Config::Get(m_setting));
|
||||
|
||||
connect(&Settings::Instance(), &Settings::ConfigChanged, [this] {
|
||||
QFont bf = font();
|
||||
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
|
||||
setFont(bf);
|
||||
|
||||
bool old = blockSignals(true);
|
||||
setCurrentIndex(Config::Get(m_setting));
|
||||
blockSignals(old);
|
||||
});
|
||||
}
|
||||
|
||||
void GraphicsChoice::Update(int choice)
|
||||
{
|
||||
Config::SetBaseOrCurrent(m_setting, choice);
|
||||
}
|
21
Source/Core/DolphinQt/Config/Graphics/GraphicsChoice.h
Normal file
21
Source/Core/DolphinQt/Config/Graphics/GraphicsChoice.h
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
#include "Common/Config/Config.h"
|
||||
|
||||
class GraphicsChoice : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GraphicsChoice(const QStringList& options, const Config::ConfigInfo<int>& setting);
|
||||
|
||||
private:
|
||||
void Update(int choice);
|
||||
|
||||
Config::ConfigInfo<int> m_setting;
|
||||
};
|
35
Source/Core/DolphinQt/Config/Graphics/GraphicsRadio.cpp
Normal file
35
Source/Core/DolphinQt/Config/Graphics/GraphicsRadio.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsRadio.h"
|
||||
|
||||
#include "Common/Config/Config.h"
|
||||
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
GraphicsRadioInt::GraphicsRadioInt(const QString& label, const Config::ConfigInfo<int>& setting,
|
||||
int value)
|
||||
: QRadioButton(label), m_setting(setting), m_value(value)
|
||||
{
|
||||
setChecked(Config::Get(m_setting) == m_value);
|
||||
connect(this, &QRadioButton::toggled, this, &GraphicsRadioInt::Update);
|
||||
|
||||
connect(&Settings::Instance(), &Settings::ConfigChanged, [this] {
|
||||
QFont bf = font();
|
||||
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
|
||||
setFont(bf);
|
||||
|
||||
bool old = blockSignals(true);
|
||||
setChecked(Config::Get(m_setting) == m_value);
|
||||
blockSignals(old);
|
||||
});
|
||||
}
|
||||
|
||||
void GraphicsRadioInt::Update()
|
||||
{
|
||||
if (!isChecked())
|
||||
return;
|
||||
|
||||
Config::SetBaseOrCurrent(m_setting, m_value);
|
||||
}
|
22
Source/Core/DolphinQt/Config/Graphics/GraphicsRadio.h
Normal file
22
Source/Core/DolphinQt/Config/Graphics/GraphicsRadio.h
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QRadioButton>
|
||||
|
||||
#include "Common/Config/Config.h"
|
||||
|
||||
class GraphicsRadioInt : public QRadioButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GraphicsRadioInt(const QString& label, const Config::ConfigInfo<int>& setting, int value);
|
||||
|
||||
private:
|
||||
void Update();
|
||||
|
||||
Config::ConfigInfo<int> m_setting;
|
||||
int m_value;
|
||||
};
|
37
Source/Core/DolphinQt/Config/Graphics/GraphicsSlider.cpp
Normal file
37
Source/Core/DolphinQt/Config/Graphics/GraphicsSlider.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsSlider.h"
|
||||
|
||||
#include "Common/Config/Config.h"
|
||||
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
GraphicsSlider::GraphicsSlider(int minimum, int maximum, const Config::ConfigInfo<int>& setting,
|
||||
int tick)
|
||||
: QSlider(Qt::Horizontal), m_setting(setting)
|
||||
{
|
||||
setMinimum(minimum);
|
||||
setMaximum(maximum);
|
||||
setTickInterval(tick);
|
||||
|
||||
setValue(Config::Get(setting));
|
||||
|
||||
connect(this, &GraphicsSlider::valueChanged, this, &GraphicsSlider::Update);
|
||||
|
||||
connect(&Settings::Instance(), &Settings::ConfigChanged, [this] {
|
||||
QFont bf = font();
|
||||
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
|
||||
setFont(bf);
|
||||
|
||||
bool old = blockSignals(true);
|
||||
setValue(Config::Get(m_setting));
|
||||
blockSignals(old);
|
||||
});
|
||||
}
|
||||
|
||||
void GraphicsSlider::Update(int value)
|
||||
{
|
||||
Config::SetBaseOrCurrent(m_setting, value);
|
||||
}
|
24
Source/Core/DolphinQt/Config/Graphics/GraphicsSlider.h
Normal file
24
Source/Core/DolphinQt/Config/Graphics/GraphicsSlider.h
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QSlider>
|
||||
|
||||
namespace Config
|
||||
{
|
||||
template <typename T>
|
||||
struct ConfigInfo;
|
||||
}
|
||||
|
||||
class GraphicsSlider : public QSlider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GraphicsSlider(int minimum, int maximum, const Config::ConfigInfo<int>& setting, int tick = 0);
|
||||
void Update(int value);
|
||||
|
||||
private:
|
||||
const Config::ConfigInfo<int>& m_setting;
|
||||
};
|
20
Source/Core/DolphinQt/Config/Graphics/GraphicsWidget.cpp
Normal file
20
Source/Core/DolphinQt/Config/Graphics/GraphicsWidget.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWidget.h"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QLabel>
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
|
||||
|
||||
GraphicsWidget::GraphicsWidget(GraphicsWindow* parent)
|
||||
{
|
||||
parent->RegisterWidget(this);
|
||||
}
|
||||
|
||||
void GraphicsWidget::AddDescription(QWidget* widget, const char* description)
|
||||
{
|
||||
emit DescriptionAdded(widget, description);
|
||||
}
|
31
Source/Core/DolphinQt/Config/Graphics/GraphicsWidget.h
Normal file
31
Source/Core/DolphinQt/Config/Graphics/GraphicsWidget.h
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class GraphicsWindow;
|
||||
class QFormLayout;
|
||||
class QGroupBox;
|
||||
class QLabel;
|
||||
|
||||
class GraphicsWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GraphicsWidget(GraphicsWindow* parent);
|
||||
|
||||
signals:
|
||||
void DescriptionAdded(QWidget* widget, const char* description);
|
||||
|
||||
protected:
|
||||
void AddDescription(QWidget* widget, const char* description);
|
||||
|
||||
virtual void LoadSettings() = 0;
|
||||
virtual void SaveSettings() = 0;
|
||||
|
||||
private:
|
||||
QFormLayout* m_main_layout;
|
||||
};
|
174
Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.cpp
Normal file
174
Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.cpp
Normal file
@ -0,0 +1,174 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QEvent>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QTabWidget>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
|
||||
#include "DolphinQt/Config/Graphics/AdvancedWidget.h"
|
||||
#include "DolphinQt/Config/Graphics/EnhancementsWidget.h"
|
||||
#include "DolphinQt/Config/Graphics/GeneralWidget.h"
|
||||
#include "DolphinQt/Config/Graphics/HacksWidget.h"
|
||||
#include "DolphinQt/Config/Graphics/SoftwareRendererWidget.h"
|
||||
#include "DolphinQt/MainWindow.h"
|
||||
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
|
||||
|
||||
#include "VideoCommon/VideoBackendBase.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
GraphicsWindow::GraphicsWindow(X11Utils::XRRConfiguration* xrr_config, MainWindow* parent)
|
||||
: QDialog(parent), m_xrr_config(xrr_config)
|
||||
{
|
||||
// GraphicsWindow initialization is heavy due to dependencies on the graphics subsystem.
|
||||
// To prevent blocking startup, we create the layout and children at first show time.
|
||||
}
|
||||
|
||||
void GraphicsWindow::Initialize()
|
||||
{
|
||||
if (m_lazy_initialized)
|
||||
return;
|
||||
|
||||
m_lazy_initialized = true;
|
||||
|
||||
g_Config.Refresh();
|
||||
g_video_backend->InitBackendInfo();
|
||||
|
||||
CreateMainLayout();
|
||||
|
||||
setWindowTitle(tr("Graphics"));
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
OnBackendChanged(QString::fromStdString(SConfig::GetInstance().m_strVideoBackend));
|
||||
}
|
||||
|
||||
void GraphicsWindow::CreateMainLayout()
|
||||
{
|
||||
auto* main_layout = new QVBoxLayout();
|
||||
auto* description_box = new QGroupBox(tr("Description"));
|
||||
auto* description_layout = new QVBoxLayout();
|
||||
m_description =
|
||||
new QLabel(tr("Move the mouse pointer over an option to display a detailed description."));
|
||||
m_tab_widget = new QTabWidget();
|
||||
m_button_box = new QDialogButtonBox(QDialogButtonBox::Close);
|
||||
|
||||
connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
description_box->setLayout(description_layout);
|
||||
description_box->setFixedHeight(200);
|
||||
|
||||
m_description->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
m_description->setWordWrap(true);
|
||||
m_description->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||
|
||||
description_layout->addWidget(m_description);
|
||||
|
||||
main_layout->addWidget(m_tab_widget);
|
||||
main_layout->addWidget(description_box);
|
||||
main_layout->addWidget(m_button_box);
|
||||
|
||||
m_general_widget = new GeneralWidget(m_xrr_config, this);
|
||||
m_enhancements_widget = new EnhancementsWidget(this);
|
||||
m_hacks_widget = new HacksWidget(this);
|
||||
m_advanced_widget = new AdvancedWidget(this);
|
||||
m_software_renderer = new SoftwareRendererWidget(this);
|
||||
|
||||
connect(m_general_widget, &GeneralWidget::BackendChanged, this,
|
||||
&GraphicsWindow::OnBackendChanged);
|
||||
connect(m_software_renderer, &SoftwareRendererWidget::BackendChanged, this,
|
||||
&GraphicsWindow::OnBackendChanged);
|
||||
|
||||
m_wrapped_general = GetWrappedWidget(m_general_widget, this, 50, 305);
|
||||
m_wrapped_enhancements = GetWrappedWidget(m_enhancements_widget, this, 50, 305);
|
||||
m_wrapped_hacks = GetWrappedWidget(m_hacks_widget, this, 50, 305);
|
||||
m_wrapped_advanced = GetWrappedWidget(m_advanced_widget, this, 50, 305);
|
||||
m_wrapped_software = GetWrappedWidget(m_software_renderer, this, 50, 305);
|
||||
|
||||
if (SConfig::GetInstance().m_strVideoBackend != "Software Renderer")
|
||||
{
|
||||
m_tab_widget->addTab(m_wrapped_general, tr("General"));
|
||||
m_tab_widget->addTab(m_wrapped_enhancements, tr("Enhancements"));
|
||||
m_tab_widget->addTab(m_wrapped_hacks, tr("Hacks"));
|
||||
m_tab_widget->addTab(m_wrapped_advanced, tr("Advanced"));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tab_widget->addTab(m_wrapped_software, tr("Software Renderer"));
|
||||
}
|
||||
|
||||
setLayout(main_layout);
|
||||
}
|
||||
|
||||
void GraphicsWindow::OnBackendChanged(const QString& backend_name)
|
||||
{
|
||||
SConfig::GetInstance().m_strVideoBackend = backend_name.toStdString();
|
||||
|
||||
for (const auto& backend : g_available_video_backends)
|
||||
{
|
||||
if (backend->GetName() == backend_name.toStdString())
|
||||
{
|
||||
g_Config.Refresh();
|
||||
|
||||
g_video_backend = backend.get();
|
||||
g_video_backend->InitBackendInfo();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setWindowTitle(
|
||||
tr("%1 Graphics Configuration").arg(tr(g_video_backend->GetDisplayName().c_str())));
|
||||
if (backend_name == QStringLiteral("Software Renderer") && m_tab_widget->count() > 1)
|
||||
{
|
||||
m_tab_widget->clear();
|
||||
m_tab_widget->addTab(m_wrapped_software, tr("Software Renderer"));
|
||||
}
|
||||
|
||||
if (backend_name != QStringLiteral("Software Renderer") && m_tab_widget->count() == 1)
|
||||
{
|
||||
m_tab_widget->clear();
|
||||
m_tab_widget->addTab(m_wrapped_general, tr("General"));
|
||||
m_tab_widget->addTab(m_wrapped_enhancements, tr("Enhancements"));
|
||||
m_tab_widget->addTab(m_wrapped_hacks, tr("Hacks"));
|
||||
m_tab_widget->addTab(m_wrapped_advanced, tr("Advanced"));
|
||||
}
|
||||
|
||||
emit BackendChanged(backend_name);
|
||||
}
|
||||
|
||||
void GraphicsWindow::RegisterWidget(GraphicsWidget* widget)
|
||||
{
|
||||
connect(widget, &GraphicsWidget::DescriptionAdded, this, &GraphicsWindow::OnDescriptionAdded);
|
||||
}
|
||||
|
||||
void GraphicsWindow::OnDescriptionAdded(QWidget* widget, const char* description)
|
||||
{
|
||||
m_widget_descriptions[widget] = description;
|
||||
widget->installEventFilter(this);
|
||||
}
|
||||
|
||||
bool GraphicsWindow::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
if (!m_widget_descriptions.contains(object))
|
||||
return false;
|
||||
|
||||
if (event->type() == QEvent::Enter)
|
||||
{
|
||||
m_description->setText(tr(m_widget_descriptions[object]));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event->type() == QEvent::Leave)
|
||||
{
|
||||
m_description->setText(
|
||||
tr("Move the mouse pointer over an option to display a detailed description."));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
65
Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.h
Normal file
65
Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.h
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QHash>
|
||||
|
||||
class AdvancedWidget;
|
||||
class EnhancementsWidget;
|
||||
class HacksWidget;
|
||||
class GeneralWidget;
|
||||
class GraphicsWidget;
|
||||
class MainWindow;
|
||||
class QLabel;
|
||||
class QTabWidget;
|
||||
class QDialogButtonBox;
|
||||
class SoftwareRendererWidget;
|
||||
|
||||
namespace X11Utils
|
||||
{
|
||||
class XRRConfiguration;
|
||||
}
|
||||
|
||||
class GraphicsWindow final : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GraphicsWindow(X11Utils::XRRConfiguration* xrr_config, MainWindow* parent);
|
||||
|
||||
void Initialize();
|
||||
|
||||
void RegisterWidget(GraphicsWidget* widget);
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
signals:
|
||||
void BackendChanged(const QString& backend);
|
||||
|
||||
private:
|
||||
void CreateMainLayout();
|
||||
void OnBackendChanged(const QString& backend);
|
||||
void OnDescriptionAdded(QWidget* widget, const char* description);
|
||||
|
||||
bool m_lazy_initialized = false;
|
||||
|
||||
QTabWidget* m_tab_widget;
|
||||
QLabel* m_description;
|
||||
QDialogButtonBox* m_button_box;
|
||||
|
||||
AdvancedWidget* m_advanced_widget;
|
||||
EnhancementsWidget* m_enhancements_widget;
|
||||
HacksWidget* m_hacks_widget;
|
||||
GeneralWidget* m_general_widget;
|
||||
SoftwareRendererWidget* m_software_renderer;
|
||||
|
||||
QWidget* m_wrapped_advanced;
|
||||
QWidget* m_wrapped_enhancements;
|
||||
QWidget* m_wrapped_hacks;
|
||||
QWidget* m_wrapped_general;
|
||||
QWidget* m_wrapped_software;
|
||||
|
||||
X11Utils::XRRConfiguration* m_xrr_config;
|
||||
|
||||
QHash<QObject*, const char*> m_widget_descriptions;
|
||||
};
|
251
Source/Core/DolphinQt/Config/Graphics/HacksWidget.cpp
Normal file
251
Source/Core/DolphinQt/Config/Graphics/HacksWidget.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Graphics/HacksWidget.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "Core/Config/GraphicsSettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsBool.h"
|
||||
#include "DolphinQt/Config/Graphics/GraphicsSlider.h"
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
HacksWidget::HacksWidget(GraphicsWindow* parent) : GraphicsWidget(parent)
|
||||
{
|
||||
CreateWidgets();
|
||||
LoadSettings();
|
||||
ConnectWidgets();
|
||||
AddDescriptions();
|
||||
|
||||
connect(parent, &GraphicsWindow::BackendChanged, this, &HacksWidget::OnBackendChanged);
|
||||
OnBackendChanged(QString::fromStdString(SConfig::GetInstance().m_strVideoBackend));
|
||||
connect(&Settings::Instance(), &Settings::ConfigChanged, this, &HacksWidget::LoadSettings);
|
||||
}
|
||||
|
||||
void HacksWidget::CreateWidgets()
|
||||
{
|
||||
auto* main_layout = new QVBoxLayout;
|
||||
|
||||
// EFB
|
||||
auto* efb_box = new QGroupBox(tr("Embedded Frame Buffer (EFB)"));
|
||||
auto* efb_layout = new QGridLayout();
|
||||
efb_box->setLayout(efb_layout);
|
||||
m_skip_efb_cpu =
|
||||
new GraphicsBool(tr("Skip EFB Access from CPU"), Config::GFX_HACK_EFB_ACCESS_ENABLE, true);
|
||||
m_ignore_format_changes = new GraphicsBool(tr("Ignore Format Changes"),
|
||||
Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES, true);
|
||||
m_store_efb_copies = new GraphicsBool(tr("Store EFB Copies to Texture Only"),
|
||||
Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);
|
||||
|
||||
efb_layout->addWidget(m_skip_efb_cpu, 0, 0);
|
||||
efb_layout->addWidget(m_ignore_format_changes, 0, 1);
|
||||
efb_layout->addWidget(m_store_efb_copies, 1, 0);
|
||||
|
||||
// Texture Cache
|
||||
auto* texture_cache_box = new QGroupBox(tr("Texture Cache"));
|
||||
auto* texture_cache_layout = new QGridLayout();
|
||||
texture_cache_box->setLayout(texture_cache_layout);
|
||||
|
||||
m_accuracy = new QSlider(Qt::Horizontal);
|
||||
m_accuracy->setMinimum(0);
|
||||
m_accuracy->setMaximum(2);
|
||||
m_accuracy->setPageStep(1);
|
||||
m_accuracy->setTickPosition(QSlider::TicksBelow);
|
||||
m_gpu_texture_decoding =
|
||||
new GraphicsBool(tr("GPU Texture Decoding"), Config::GFX_ENABLE_GPU_TEXTURE_DECODING);
|
||||
|
||||
auto* safe_label = new QLabel(tr("Safe"));
|
||||
safe_label->setAlignment(Qt::AlignRight);
|
||||
|
||||
m_accuracy_label = new QLabel(tr("Accuracy:"));
|
||||
|
||||
texture_cache_layout->addWidget(m_accuracy_label, 0, 0);
|
||||
texture_cache_layout->addWidget(safe_label, 0, 1);
|
||||
texture_cache_layout->addWidget(m_accuracy, 0, 2);
|
||||
texture_cache_layout->addWidget(new QLabel(tr("Fast")), 0, 3);
|
||||
texture_cache_layout->addWidget(m_gpu_texture_decoding, 1, 0);
|
||||
|
||||
// XFB
|
||||
auto* xfb_box = new QGroupBox(tr("External Frame Buffer (XFB)"));
|
||||
auto* xfb_layout = new QVBoxLayout();
|
||||
xfb_box->setLayout(xfb_layout);
|
||||
|
||||
m_store_xfb_copies = new GraphicsBool(tr("Store XFB Copies to Texture Only"),
|
||||
Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM);
|
||||
m_immediate_xfb = new GraphicsBool(tr("Immediately Present XFB"), Config::GFX_HACK_IMMEDIATE_XFB);
|
||||
|
||||
xfb_layout->addWidget(m_store_xfb_copies);
|
||||
xfb_layout->addWidget(m_immediate_xfb);
|
||||
|
||||
// Other
|
||||
auto* other_box = new QGroupBox(tr("Other"));
|
||||
auto* other_layout = new QGridLayout();
|
||||
other_box->setLayout(other_layout);
|
||||
|
||||
m_fast_depth_calculation =
|
||||
new GraphicsBool(tr("Fast Depth Calculation"), Config::GFX_FAST_DEPTH_CALC);
|
||||
m_disable_bounding_box =
|
||||
new GraphicsBool(tr("Disable Bounding Box"), Config::GFX_HACK_BBOX_ENABLE, true);
|
||||
m_vertex_rounding = new GraphicsBool(tr("Vertex Rounding"), Config::GFX_HACK_VERTEX_ROUDING);
|
||||
|
||||
other_layout->addWidget(m_fast_depth_calculation, 0, 0);
|
||||
other_layout->addWidget(m_disable_bounding_box, 0, 1);
|
||||
other_layout->addWidget(m_vertex_rounding, 1, 0);
|
||||
|
||||
main_layout->addWidget(efb_box);
|
||||
main_layout->addWidget(texture_cache_box);
|
||||
main_layout->addWidget(xfb_box);
|
||||
main_layout->addWidget(other_box);
|
||||
main_layout->addStretch();
|
||||
|
||||
setLayout(main_layout);
|
||||
}
|
||||
|
||||
void HacksWidget::OnBackendChanged(const QString& backend_name)
|
||||
{
|
||||
const bool bbox = g_Config.backend_info.bSupportsBBox;
|
||||
const bool gpu_texture_decoding = g_Config.backend_info.bSupportsGPUTextureDecoding;
|
||||
|
||||
m_gpu_texture_decoding->setEnabled(gpu_texture_decoding);
|
||||
m_disable_bounding_box->setEnabled(bbox);
|
||||
|
||||
if (!gpu_texture_decoding)
|
||||
m_gpu_texture_decoding->setToolTip(tr("%1 doesn't support this feature.").arg(backend_name));
|
||||
|
||||
if (!bbox)
|
||||
m_disable_bounding_box->setToolTip(tr("%1 doesn't support this feature.").arg(backend_name));
|
||||
}
|
||||
|
||||
void HacksWidget::ConnectWidgets()
|
||||
{
|
||||
connect(m_accuracy, &QSlider::valueChanged, [this](int) { SaveSettings(); });
|
||||
}
|
||||
|
||||
void HacksWidget::LoadSettings()
|
||||
{
|
||||
const bool old = m_accuracy->blockSignals(true);
|
||||
auto samples = Config::Get(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES);
|
||||
|
||||
int slider_pos = 0;
|
||||
|
||||
switch (samples)
|
||||
{
|
||||
case 512:
|
||||
slider_pos = 1;
|
||||
break;
|
||||
case 128:
|
||||
slider_pos = 2;
|
||||
break;
|
||||
case 0:
|
||||
slider_pos = 0;
|
||||
break;
|
||||
// Custom values, ought not to be touched
|
||||
default:
|
||||
m_accuracy->setEnabled(false);
|
||||
}
|
||||
|
||||
m_accuracy->setValue(slider_pos);
|
||||
|
||||
QFont bf = m_accuracy_label->font();
|
||||
|
||||
bf.setBold(Config::GetActiveLayerForConfig(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES) !=
|
||||
Config::LayerType::Base);
|
||||
|
||||
m_accuracy_label->setFont(bf);
|
||||
|
||||
m_accuracy->blockSignals(old);
|
||||
}
|
||||
|
||||
void HacksWidget::SaveSettings()
|
||||
{
|
||||
int slider_pos = m_accuracy->value();
|
||||
|
||||
if (m_accuracy->isEnabled())
|
||||
{
|
||||
int samples = 0;
|
||||
switch (slider_pos)
|
||||
{
|
||||
case 0:
|
||||
samples = 0;
|
||||
break;
|
||||
case 1:
|
||||
samples = 512;
|
||||
break;
|
||||
case 2:
|
||||
samples = 128;
|
||||
}
|
||||
|
||||
Config::SetBaseOrCurrent(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES, samples);
|
||||
}
|
||||
}
|
||||
|
||||
void HacksWidget::AddDescriptions()
|
||||
{
|
||||
static const char TR_SKIP_EFB_CPU_ACCESS_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Ignore any requests from the CPU to read from or write to the EFB.\nImproves "
|
||||
"performance in some games, but might disable some gameplay-related features or "
|
||||
"graphical effects.\n\nIf unsure, leave this unchecked.");
|
||||
static const char TR_IGNORE_FORMAT_CHANGE_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Ignore any changes to the EFB format.\nImproves performance in many games without "
|
||||
"any negative effect. Causes graphical defects in a small number of other "
|
||||
"games.\n\nIf unsure, leave this checked.");
|
||||
static const char TR_STORE_EFB_TO_TEXTURE_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Stores EFB Copies exclusively on the GPU, bypassing system memory. Causes graphical defects "
|
||||
"in a small number of games.\n\nEnabled = EFB Copies to Texture\nDisabled = EFB Copies to "
|
||||
"RAM "
|
||||
"(and Texture)\n\nIf unsure, leave this checked.");
|
||||
static const char TR_ACCUARCY_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"The \"Safe\" setting eliminates the likelihood of the GPU missing texture updates "
|
||||
"from RAM.\nLower accuracies cause in-game text to appear garbled in certain "
|
||||
"games.\n\nIf unsure, use the rightmost value.");
|
||||
|
||||
static const char TR_STORE_XFB_TO_TEXTURE_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Stores XFB Copies exclusively on the GPU, bypassing system memory. Causes graphical defects "
|
||||
"in a small number of games that need to readback from memory.\n\nEnabled = XFB Copies to "
|
||||
"Texture\nDisabled = XFB Copies to RAM "
|
||||
"(and Texture)\n\nIf unsure, leave this checked.");
|
||||
|
||||
static const char TR_IMMEDIATE_XFB_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Displays the XFB copies as soon as they are created, without waiting for "
|
||||
"scanout. Can cause graphical defects "
|
||||
"in some games if the game doesn't expect all XFB copies to be displayed. "
|
||||
"However, turning this setting on reduces latency."
|
||||
"\n\nIf unsure, leave this unchecked.");
|
||||
|
||||
static const char TR_GPU_DECODING_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Enables texture decoding using the GPU instead of the CPU. This may result in "
|
||||
"performance gains in some scenarios, or on systems where the CPU is the "
|
||||
"bottleneck.\n\nIf unsure, leave this unchecked.");
|
||||
|
||||
static const char TR_FAST_DEPTH_CALC_DESCRIPTION[] = QT_TR_NOOP(
|
||||
"Use a less accurate algorithm to calculate depth values.\nCauses issues in a few "
|
||||
"games, but can give a decent speedup depending on the game and/or your GPU.\n\nIf "
|
||||
"unsure, leave this checked.");
|
||||
static const char TR_DISABLE_BOUNDINGBOX_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Disable the bounding box emulation.\nThis may improve the GPU performance a lot, "
|
||||
"but some games will break.\n\nIf unsure, leave this checked.");
|
||||
static const char TR_VERTEX_ROUNDING_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Rounds 2D vertices to whole pixels. Fixes graphical problems in some games at "
|
||||
"higher internal resolutions. This setting has no effect when native internal "
|
||||
"resolution is used.\n\nIf unsure, leave this unchecked.");
|
||||
|
||||
AddDescription(m_skip_efb_cpu, TR_SKIP_EFB_CPU_ACCESS_DESCRIPTION);
|
||||
AddDescription(m_ignore_format_changes, TR_IGNORE_FORMAT_CHANGE_DESCRIPTION);
|
||||
AddDescription(m_store_efb_copies, TR_STORE_EFB_TO_TEXTURE_DESCRIPTION);
|
||||
AddDescription(m_accuracy, TR_ACCUARCY_DESCRIPTION);
|
||||
AddDescription(m_store_xfb_copies, TR_STORE_XFB_TO_TEXTURE_DESCRIPTION);
|
||||
AddDescription(m_immediate_xfb, TR_IMMEDIATE_XFB_DESCRIPTION);
|
||||
AddDescription(m_gpu_texture_decoding, TR_GPU_DECODING_DESCRIPTION);
|
||||
AddDescription(m_fast_depth_calculation, TR_FAST_DEPTH_CALC_DESCRIPTION);
|
||||
AddDescription(m_disable_bounding_box, TR_DISABLE_BOUNDINGBOX_DESCRIPTION);
|
||||
AddDescription(m_vertex_rounding, TR_VERTEX_ROUNDING_DESCRIPTION);
|
||||
}
|
49
Source/Core/DolphinQt/Config/Graphics/HacksWidget.h
Normal file
49
Source/Core/DolphinQt/Config/Graphics/HacksWidget.h
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWidget.h"
|
||||
|
||||
class GraphicsWindow;
|
||||
class QCheckBox;
|
||||
class QLabel;
|
||||
class QRadioButton;
|
||||
class QSlider;
|
||||
|
||||
class HacksWidget final : public GraphicsWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HacksWidget(GraphicsWindow* parent);
|
||||
|
||||
private:
|
||||
void LoadSettings() override;
|
||||
void SaveSettings() override;
|
||||
|
||||
void OnBackendChanged(const QString& backend_name);
|
||||
|
||||
// EFB
|
||||
QCheckBox* m_skip_efb_cpu;
|
||||
QCheckBox* m_ignore_format_changes;
|
||||
QCheckBox* m_store_efb_copies;
|
||||
|
||||
// Texture Cache
|
||||
QLabel* m_accuracy_label;
|
||||
QSlider* m_accuracy;
|
||||
QCheckBox* m_gpu_texture_decoding;
|
||||
|
||||
// External Framebuffer
|
||||
QCheckBox* m_store_xfb_copies;
|
||||
QCheckBox* m_immediate_xfb;
|
||||
|
||||
// Other
|
||||
QCheckBox* m_fast_depth_calculation;
|
||||
QCheckBox* m_disable_bounding_box;
|
||||
QCheckBox* m_vertex_rounding;
|
||||
|
||||
void CreateWidgets();
|
||||
void ConnectWidgets();
|
||||
void AddDescriptions();
|
||||
};
|
@ -0,0 +1,362 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Graphics/PostProcessingConfigWindow.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QSlider>
|
||||
#include <QString>
|
||||
#include <QTabWidget>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include "DolphinQt/Config/Graphics/EnhancementsWidget.h"
|
||||
|
||||
#include "VideoCommon/PostProcessing.h"
|
||||
#include "VideoCommon/RenderBase.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
using ConfigurationOption = PostProcessingShaderConfiguration::ConfigurationOption;
|
||||
using OptionType = ConfigurationOption::OptionType;
|
||||
|
||||
PostProcessingConfigWindow::PostProcessingConfigWindow(EnhancementsWidget* parent,
|
||||
const std::string& shader)
|
||||
: QDialog(parent), m_shader(shader)
|
||||
{
|
||||
if (g_renderer && g_renderer->GetPostProcessor())
|
||||
{
|
||||
m_post_processor = g_renderer->GetPostProcessor()->GetConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_post_processor = new PostProcessingShaderConfiguration();
|
||||
m_post_processor->LoadShader(m_shader);
|
||||
}
|
||||
|
||||
setWindowTitle(tr("Post Processing Shader Configuration"));
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
PopulateGroups();
|
||||
Create();
|
||||
ConnectWidgets();
|
||||
}
|
||||
|
||||
PostProcessingConfigWindow::~PostProcessingConfigWindow()
|
||||
{
|
||||
m_post_processor->SaveOptionsConfiguration();
|
||||
if (!(g_renderer && g_renderer->GetPostProcessor()))
|
||||
{
|
||||
delete m_post_processor;
|
||||
}
|
||||
}
|
||||
|
||||
void PostProcessingConfigWindow::PopulateGroups()
|
||||
{
|
||||
const PostProcessingShaderConfiguration::ConfigMap& config_map = m_post_processor->GetOptions();
|
||||
|
||||
auto config_groups = std::vector<std::unique_ptr<ConfigGroup>>();
|
||||
for (const auto& it : config_map)
|
||||
{
|
||||
auto config_group = std::make_unique<ConfigGroup>(&it.second);
|
||||
m_config_map[it.first] = config_group.get();
|
||||
config_groups.push_back(std::move(config_group));
|
||||
}
|
||||
|
||||
for (auto& config_group : config_groups)
|
||||
{
|
||||
const std::string& parent_name = config_group->GetParent();
|
||||
if (parent_name.empty())
|
||||
{
|
||||
m_config_groups.emplace_back(std::move(config_group));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_config_map[parent_name]->AddSubGroup(std::move(config_group));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PostProcessingConfigWindow::Create()
|
||||
{
|
||||
m_tabs = new QTabWidget();
|
||||
auto* const general = new QWidget(m_tabs);
|
||||
auto* const general_layout = new QGridLayout(general);
|
||||
|
||||
u32 row = 0;
|
||||
bool add_general_page = false;
|
||||
for (const auto& it : m_config_groups)
|
||||
{
|
||||
if (it->HasSubGroups())
|
||||
{
|
||||
auto* const tab = CreateDependentTab(it);
|
||||
m_tabs->addTab(tab, QString::fromStdString(it->GetGUIName()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!add_general_page)
|
||||
{
|
||||
add_general_page = true;
|
||||
}
|
||||
row = it->AddWidgets(this, general_layout, row);
|
||||
}
|
||||
}
|
||||
|
||||
if (add_general_page)
|
||||
{
|
||||
m_tabs->insertTab(0, general, tr("General"));
|
||||
}
|
||||
|
||||
m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok);
|
||||
|
||||
auto* layout = new QVBoxLayout(this);
|
||||
layout->addWidget(m_tabs);
|
||||
layout->addWidget(m_buttons);
|
||||
}
|
||||
|
||||
void PostProcessingConfigWindow::ConnectWidgets()
|
||||
{
|
||||
connect(m_buttons, &QDialogButtonBox::accepted, this, &PostProcessingConfigWindow::accept);
|
||||
}
|
||||
|
||||
QWidget*
|
||||
PostProcessingConfigWindow::CreateDependentTab(const std::unique_ptr<ConfigGroup>& config_group)
|
||||
{
|
||||
auto* const tab = new QWidget(m_tabs);
|
||||
auto* const layout = new QGridLayout(tab);
|
||||
|
||||
u32 row = config_group->AddWidgets(this, layout, 0);
|
||||
for (const auto& child : config_group->GetSubGroups())
|
||||
{
|
||||
row = child->AddWidgets(this, layout, row);
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
void PostProcessingConfigWindow::UpdateBool(ConfigGroup* const config_group, const bool state)
|
||||
{
|
||||
m_post_processor->SetOptionb(config_group->GetOptionName(), state);
|
||||
|
||||
config_group->EnableSuboptions(state);
|
||||
}
|
||||
|
||||
void PostProcessingConfigWindow::UpdateInteger(ConfigGroup* const config_group, const int value)
|
||||
{
|
||||
const ConfigurationOption& config_option =
|
||||
m_post_processor->GetOption(config_group->GetOptionName());
|
||||
|
||||
const size_t vector_size = config_option.m_integer_values.size();
|
||||
|
||||
for (size_t i = 0; i < vector_size; ++i)
|
||||
{
|
||||
const int current_step = config_group->GetSliderValue(i);
|
||||
const s32 current_value = config_option.m_integer_step_values[i] * current_step +
|
||||
config_option.m_integer_min_values[i];
|
||||
m_post_processor->SetOptioni(config_option.m_option_name, static_cast<int>(i), current_value);
|
||||
config_group->SetSliderText(i, QString::number(current_value));
|
||||
}
|
||||
}
|
||||
|
||||
void PostProcessingConfigWindow::UpdateFloat(ConfigGroup* const config_group, const int value)
|
||||
{
|
||||
const ConfigurationOption& config_option =
|
||||
m_post_processor->GetOption(config_group->GetOptionName());
|
||||
|
||||
const size_t vector_size = config_option.m_float_values.size();
|
||||
|
||||
for (size_t i = 0; i < vector_size; ++i)
|
||||
{
|
||||
const int current_step = config_group->GetSliderValue(static_cast<unsigned int>(i));
|
||||
const float current_value =
|
||||
config_option.m_float_step_values[i] * current_step + config_option.m_float_min_values[i];
|
||||
m_post_processor->SetOptionf(config_option.m_option_name, static_cast<int>(i), current_value);
|
||||
config_group->SetSliderText(i, QString::asprintf("%f", current_value));
|
||||
}
|
||||
}
|
||||
|
||||
PostProcessingConfigWindow::ConfigGroup::ConfigGroup(const ConfigurationOption* config_option)
|
||||
: m_config_option(config_option)
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& PostProcessingConfigWindow::ConfigGroup::GetGUIName() const noexcept
|
||||
{
|
||||
return m_config_option->m_gui_name;
|
||||
}
|
||||
|
||||
const std::string& PostProcessingConfigWindow::ConfigGroup::GetParent() const noexcept
|
||||
{
|
||||
return m_config_option->m_dependent_option;
|
||||
}
|
||||
|
||||
const std::string& PostProcessingConfigWindow::ConfigGroup::GetOptionName() const noexcept
|
||||
{
|
||||
return m_config_option->m_option_name;
|
||||
}
|
||||
|
||||
void PostProcessingConfigWindow::ConfigGroup::AddSubGroup(std::unique_ptr<ConfigGroup>&& subgroup)
|
||||
{
|
||||
m_subgroups.emplace_back(std::move(subgroup));
|
||||
}
|
||||
|
||||
bool PostProcessingConfigWindow::ConfigGroup::HasSubGroups() const noexcept
|
||||
{
|
||||
return !m_subgroups.empty();
|
||||
}
|
||||
|
||||
const std::vector<std::unique_ptr<PostProcessingConfigWindow::ConfigGroup>>&
|
||||
PostProcessingConfigWindow::ConfigGroup::GetSubGroups() const noexcept
|
||||
{
|
||||
return m_subgroups;
|
||||
}
|
||||
|
||||
u32 PostProcessingConfigWindow::ConfigGroup::AddWidgets(PostProcessingConfigWindow* const parent,
|
||||
QGridLayout* const grid, const u32 row)
|
||||
{
|
||||
auto* const name = new QLabel(QString::fromStdString(m_config_option->m_gui_name));
|
||||
grid->addWidget(name, row, 0);
|
||||
|
||||
switch (m_config_option->m_type)
|
||||
{
|
||||
case OptionType::OPTION_BOOL:
|
||||
return AddBool(parent, grid, row);
|
||||
case OptionType::OPTION_FLOAT:
|
||||
return AddFloat(parent, grid, row);
|
||||
case OptionType::OPTION_INTEGER:
|
||||
return AddInteger(parent, grid, row);
|
||||
default:
|
||||
// obviously shouldn't get here
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
u32 PostProcessingConfigWindow::ConfigGroup::AddBool(PostProcessingConfigWindow* const parent,
|
||||
QGridLayout* const grid, const u32 row)
|
||||
{
|
||||
m_checkbox = new QCheckBox();
|
||||
m_checkbox->setChecked(m_config_option->m_bool_value);
|
||||
QObject::connect(m_checkbox, &QCheckBox::toggled,
|
||||
[this, parent](bool checked) { parent->UpdateBool(this, checked); });
|
||||
grid->addWidget(m_checkbox, row, 2);
|
||||
|
||||
return row + 1;
|
||||
}
|
||||
|
||||
u32 PostProcessingConfigWindow::ConfigGroup::AddInteger(PostProcessingConfigWindow* const parent,
|
||||
QGridLayout* const grid, u32 row)
|
||||
{
|
||||
const size_t vector_size = m_config_option->m_integer_values.size();
|
||||
|
||||
for (size_t i = 0; i < vector_size; ++i)
|
||||
{
|
||||
const int current_value = m_config_option->m_integer_values[i];
|
||||
const double range =
|
||||
m_config_option->m_integer_max_values[i] - m_config_option->m_integer_min_values[i];
|
||||
// "How many steps we have is the range divided by the step interval configured.
|
||||
// This may not be 100% spot on accurate since developers can have odd stepping intervals
|
||||
// set.
|
||||
// Round up so if it is outside our range, then set it to the minimum or maximum"
|
||||
const int steps =
|
||||
std::ceil(range / static_cast<double>(m_config_option->m_integer_step_values[i]));
|
||||
|
||||
auto* const slider = new QSlider(Qt::Orientation::Horizontal);
|
||||
slider->setMinimum(0);
|
||||
slider->setMaximum(steps);
|
||||
slider->setValue(current_value);
|
||||
slider->setTickInterval(range / steps);
|
||||
QObject::connect(slider, &QSlider::valueChanged,
|
||||
[this, parent](int value) { parent->UpdateInteger(this, value); });
|
||||
|
||||
auto* const value_box = new QLineEdit(QString::number(current_value));
|
||||
value_box->setEnabled(false);
|
||||
|
||||
grid->addWidget(slider, row, 1);
|
||||
grid->addWidget(value_box, row, 2);
|
||||
|
||||
m_sliders.push_back(slider);
|
||||
m_value_boxes.push_back(value_box);
|
||||
if (vector_size > 1)
|
||||
{
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
return row + 1;
|
||||
}
|
||||
|
||||
u32 PostProcessingConfigWindow::ConfigGroup::AddFloat(PostProcessingConfigWindow* const parent,
|
||||
QGridLayout* const grid, u32 row)
|
||||
{
|
||||
const size_t vector_size = m_config_option->m_float_values.size();
|
||||
|
||||
for (size_t i = 0; i < vector_size; ++i)
|
||||
{
|
||||
const int current_value =
|
||||
m_config_option->m_float_values[i] / m_config_option->m_float_step_values[i];
|
||||
const float range =
|
||||
m_config_option->m_float_max_values[i] - m_config_option->m_float_min_values[i];
|
||||
const int steps = std::ceil(range / m_config_option->m_float_step_values[i]);
|
||||
|
||||
auto* const slider = new QSlider(Qt::Orientation::Horizontal);
|
||||
slider->setMinimum(0);
|
||||
slider->setMaximum(steps);
|
||||
slider->setValue(current_value);
|
||||
slider->setTickInterval(range / steps);
|
||||
QObject::connect(slider, &QSlider::valueChanged,
|
||||
[this, parent](int value) { parent->UpdateFloat(this, value); });
|
||||
|
||||
auto* const value_box =
|
||||
new QLineEdit(QString::asprintf("%f", m_config_option->m_float_values[i]));
|
||||
value_box->setEnabled(false);
|
||||
|
||||
grid->addWidget(slider, row, 1);
|
||||
grid->addWidget(value_box, row, 2);
|
||||
|
||||
m_sliders.push_back(slider);
|
||||
m_value_boxes.push_back(value_box);
|
||||
if (vector_size > 1)
|
||||
{
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
return row + 1;
|
||||
}
|
||||
|
||||
void PostProcessingConfigWindow::ConfigGroup::EnableSuboptions(const bool state)
|
||||
{
|
||||
for (auto& it : m_subgroups)
|
||||
{
|
||||
if (it->m_config_option->m_type == OptionType::OPTION_BOOL)
|
||||
{
|
||||
it->m_checkbox->setEnabled(state);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& slider : it->m_sliders)
|
||||
{
|
||||
slider->setEnabled(state);
|
||||
}
|
||||
}
|
||||
it->EnableSuboptions(state);
|
||||
}
|
||||
}
|
||||
|
||||
int PostProcessingConfigWindow::ConfigGroup::GetSliderValue(size_t index) const
|
||||
{
|
||||
return m_sliders[index]->value();
|
||||
}
|
||||
|
||||
void PostProcessingConfigWindow::ConfigGroup::SetSliderText(size_t index, const QString& text)
|
||||
{
|
||||
m_value_boxes[index]->setText(text);
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoCommon/PostProcessing.h"
|
||||
|
||||
class EnhancementsWidget;
|
||||
class QCheckBox;
|
||||
class QDialogButtonBox;
|
||||
class QGridLayout;
|
||||
class QLineEdit;
|
||||
class QSlider;
|
||||
class QTabWidget;
|
||||
class QWidget;
|
||||
|
||||
class PostProcessingConfigWindow final : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PostProcessingConfigWindow(EnhancementsWidget* parent, const std::string& shader);
|
||||
~PostProcessingConfigWindow();
|
||||
|
||||
private:
|
||||
class ConfigGroup final
|
||||
{
|
||||
public:
|
||||
explicit ConfigGroup(
|
||||
const PostProcessingShaderConfiguration::ConfigurationOption* config_option);
|
||||
|
||||
const std::string& GetGUIName() const noexcept;
|
||||
const std::string& GetParent() const noexcept;
|
||||
const std::string& GetOptionName() const noexcept;
|
||||
void AddSubGroup(std::unique_ptr<ConfigGroup>&& subgroup);
|
||||
bool HasSubGroups() const noexcept;
|
||||
const std::vector<std::unique_ptr<ConfigGroup>>& GetSubGroups() const noexcept;
|
||||
u32 AddWidgets(PostProcessingConfigWindow* parent, QGridLayout* grid, u32 row);
|
||||
void EnableSuboptions(bool state);
|
||||
int GetSliderValue(size_t index) const;
|
||||
void SetSliderText(size_t index, const QString& text);
|
||||
|
||||
private:
|
||||
u32 AddBool(PostProcessingConfigWindow* parent, QGridLayout* grid, u32 row);
|
||||
u32 AddInteger(PostProcessingConfigWindow* parent, QGridLayout* grid, u32 row);
|
||||
u32 AddFloat(PostProcessingConfigWindow* parent, QGridLayout* grid, u32 row);
|
||||
|
||||
QCheckBox* m_checkbox;
|
||||
std::vector<QSlider*> m_sliders;
|
||||
std::vector<QLineEdit*> m_value_boxes;
|
||||
|
||||
const PostProcessingShaderConfiguration::ConfigurationOption* m_config_option;
|
||||
std::vector<std::unique_ptr<ConfigGroup>> m_subgroups;
|
||||
};
|
||||
void Create();
|
||||
void ConnectWidgets();
|
||||
QWidget* CreateDependentTab(const std::unique_ptr<ConfigGroup>& config_group);
|
||||
void PopulateGroups();
|
||||
void UpdateBool(ConfigGroup* config_group, bool state);
|
||||
void UpdateInteger(ConfigGroup* config_group, int value);
|
||||
void UpdateFloat(ConfigGroup* config_group, int value);
|
||||
|
||||
QTabWidget* m_tabs;
|
||||
QDialogButtonBox* m_buttons;
|
||||
|
||||
const std::string& m_shader;
|
||||
PostProcessingShaderConfiguration* m_post_processor;
|
||||
std::unordered_map<std::string, ConfigGroup*> m_config_map;
|
||||
std::vector<std::unique_ptr<ConfigGroup>> m_config_groups;
|
||||
};
|
182
Source/Core/DolphinQt/Config/Graphics/SoftwareRendererWidget.cpp
Normal file
182
Source/Core/DolphinQt/Config/Graphics/SoftwareRendererWidget.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/Config/Graphics/SoftwareRendererWidget.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QSpinBox>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "Core/Config/GraphicsSettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsBool.h"
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
#include "UICommon/VideoUtils.h"
|
||||
|
||||
#include "VideoCommon/VideoBackendBase.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
SoftwareRendererWidget::SoftwareRendererWidget(GraphicsWindow* parent) : GraphicsWidget(parent)
|
||||
{
|
||||
CreateWidgets();
|
||||
|
||||
connect(parent, &GraphicsWindow::BackendChanged, [this] { LoadSettings(); });
|
||||
|
||||
LoadSettings();
|
||||
ConnectWidgets();
|
||||
AddDescriptions();
|
||||
}
|
||||
|
||||
void SoftwareRendererWidget::CreateWidgets()
|
||||
{
|
||||
auto* main_layout = new QVBoxLayout;
|
||||
|
||||
auto* rendering_box = new QGroupBox(tr("Rendering"));
|
||||
auto* rendering_layout = new QGridLayout();
|
||||
m_backend_combo = new QComboBox();
|
||||
|
||||
rendering_box->setLayout(rendering_layout);
|
||||
rendering_layout->addWidget(new QLabel(tr("Backend:")), 1, 1);
|
||||
rendering_layout->addWidget(m_backend_combo, 1, 2);
|
||||
|
||||
for (const auto& backend : g_available_video_backends)
|
||||
m_backend_combo->addItem(tr(backend->GetDisplayName().c_str()));
|
||||
|
||||
auto* overlay_box = new QGroupBox(tr("Overlay Information"));
|
||||
auto* overlay_layout = new QGridLayout();
|
||||
overlay_box->setLayout(overlay_layout);
|
||||
m_show_statistics = new GraphicsBool(tr("Show Statistics"), Config::GFX_OVERLAY_STATS);
|
||||
|
||||
overlay_layout->addWidget(m_show_statistics);
|
||||
|
||||
auto* utility_box = new QGroupBox(tr("Utility"));
|
||||
auto* utility_layout = new QGridLayout();
|
||||
m_dump_textures = new GraphicsBool(tr("Dump Textures"), Config::GFX_DUMP_TEXTURES);
|
||||
m_dump_objects = new GraphicsBool(tr("Dump Objects"), Config::GFX_SW_DUMP_OBJECTS);
|
||||
utility_box->setLayout(utility_layout);
|
||||
|
||||
utility_layout->addWidget(m_dump_textures, 1, 1);
|
||||
utility_layout->addWidget(m_dump_objects, 1, 2);
|
||||
|
||||
auto* debug_box = new QGroupBox(tr("Debug Only"));
|
||||
auto* debug_layout = new QGridLayout();
|
||||
m_dump_tev_stages = new GraphicsBool(tr("Dump TEV Stages"), Config::GFX_SW_DUMP_TEV_STAGES);
|
||||
m_dump_tev_fetches =
|
||||
new GraphicsBool(tr("Dump Texture Fetches"), Config::GFX_SW_DUMP_TEV_TEX_FETCHES);
|
||||
|
||||
debug_layout->addWidget(m_dump_tev_stages, 1, 1);
|
||||
debug_layout->addWidget(m_dump_tev_fetches, 1, 2);
|
||||
|
||||
debug_box->setLayout(debug_layout);
|
||||
|
||||
#ifdef _DEBUG
|
||||
utility_layout->addWidget(debug_box, 2, 1, 1, 2);
|
||||
#endif
|
||||
|
||||
auto* object_range_box = new QGroupBox(tr("Drawn Object Range"));
|
||||
auto* object_range_layout = new QGridLayout();
|
||||
m_object_range_min = new QSpinBox();
|
||||
m_object_range_max = new QSpinBox();
|
||||
|
||||
for (auto* spin : {m_object_range_min, m_object_range_max})
|
||||
{
|
||||
spin->setMinimum(0);
|
||||
spin->setMaximum(100000);
|
||||
}
|
||||
|
||||
object_range_box->setLayout(object_range_layout);
|
||||
|
||||
object_range_layout->addWidget(m_object_range_min, 1, 1);
|
||||
object_range_layout->addWidget(m_object_range_max, 1, 2);
|
||||
|
||||
main_layout->addWidget(rendering_box);
|
||||
main_layout->addWidget(overlay_box);
|
||||
main_layout->addWidget(utility_box);
|
||||
main_layout->addWidget(object_range_box);
|
||||
main_layout->addStretch();
|
||||
|
||||
setLayout(main_layout);
|
||||
}
|
||||
|
||||
void SoftwareRendererWidget::ConnectWidgets()
|
||||
{
|
||||
connect(m_backend_combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
[this](int) { SaveSettings(); });
|
||||
connect(m_object_range_min, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
||||
[this](int) { SaveSettings(); });
|
||||
connect(m_object_range_max, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
||||
[this](int) { SaveSettings(); });
|
||||
}
|
||||
|
||||
void SoftwareRendererWidget::LoadSettings()
|
||||
{
|
||||
for (const auto& backend : g_available_video_backends)
|
||||
{
|
||||
if (backend->GetName() == SConfig::GetInstance().m_strVideoBackend)
|
||||
m_backend_combo->setCurrentIndex(
|
||||
m_backend_combo->findText(tr(backend->GetDisplayName().c_str())));
|
||||
}
|
||||
|
||||
m_object_range_min->setValue(Config::Get(Config::GFX_SW_DRAW_START));
|
||||
m_object_range_max->setValue(Config::Get(Config::GFX_SW_DRAW_END));
|
||||
}
|
||||
|
||||
void SoftwareRendererWidget::SaveSettings()
|
||||
{
|
||||
for (const auto& backend : g_available_video_backends)
|
||||
{
|
||||
if (tr(backend->GetDisplayName().c_str()) == m_backend_combo->currentText())
|
||||
{
|
||||
const auto backend_name = backend->GetName();
|
||||
if (backend_name != SConfig::GetInstance().m_strVideoBackend)
|
||||
emit BackendChanged(QString::fromStdString(backend_name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Config::SetBaseOrCurrent(Config::GFX_SW_DRAW_START, m_object_range_min->value());
|
||||
Config::SetBaseOrCurrent(Config::GFX_SW_DRAW_END, m_object_range_max->value());
|
||||
}
|
||||
|
||||
void SoftwareRendererWidget::AddDescriptions()
|
||||
{
|
||||
static const char TR_BACKEND_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Selects what graphics API to use internally.\nThe software renderer is extremely "
|
||||
"slow and only useful for debugging, so you'll want to use either Direct3D or "
|
||||
"OpenGL. Different games and different GPUs will behave differently on each "
|
||||
"backend, so for the best emulation experience it's recommended to try both and "
|
||||
"choose the one that's less problematic.\n\nIf unsure, select OpenGL.");
|
||||
|
||||
static const char TR_SHOW_STATISTICS_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Show various rendering statistics.\n\nIf unsure, leave this unchecked.");
|
||||
|
||||
static const char TR_DUMP_TEXTURES_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Dump decoded game textures to User/Dump/Textures/<game_id>/.\n\nIf unsure, leave "
|
||||
"this unchecked.");
|
||||
|
||||
static const char TR_DUMP_OBJECTS_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Dump objects to User/Dump/Objects/.\n\nIf unsure, leave "
|
||||
"this unchecked.");
|
||||
|
||||
static const char TR_DUMP_TEV_STAGES_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Dump TEV Stages to User/Dump/Objects/.\n\nIf unsure, leave "
|
||||
"this unchecked.");
|
||||
|
||||
static const char TR_DUMP_TEV_FETCHES_DESCRIPTION[] =
|
||||
QT_TR_NOOP("Dump Texture Fetches to User/Dump/Objects/.\n\nIf unsure, leave "
|
||||
"this unchecked.");
|
||||
|
||||
AddDescription(m_backend_combo, TR_BACKEND_DESCRIPTION);
|
||||
AddDescription(m_show_statistics, TR_SHOW_STATISTICS_DESCRIPTION);
|
||||
AddDescription(m_dump_textures, TR_DUMP_TEXTURES_DESCRIPTION);
|
||||
AddDescription(m_dump_objects, TR_DUMP_OBJECTS_DESCRIPTION);
|
||||
AddDescription(m_dump_tev_stages, TR_DUMP_TEV_STAGES_DESCRIPTION);
|
||||
AddDescription(m_dump_tev_fetches, TR_DUMP_TEV_FETCHES_DESCRIPTION);
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DolphinQt/Config/Graphics/GraphicsWidget.h"
|
||||
|
||||
class GraphicsWindow;
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QSpinBox;
|
||||
|
||||
class SoftwareRendererWidget final : public GraphicsWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SoftwareRendererWidget(GraphicsWindow* parent);
|
||||
|
||||
signals:
|
||||
void BackendChanged(const QString& backend);
|
||||
|
||||
private:
|
||||
void LoadSettings() override;
|
||||
void SaveSettings() override;
|
||||
|
||||
void CreateWidgets();
|
||||
void ConnectWidgets();
|
||||
void AddDescriptions();
|
||||
|
||||
QComboBox* m_backend_combo;
|
||||
QCheckBox* m_show_statistics;
|
||||
QCheckBox* m_dump_textures;
|
||||
QCheckBox* m_dump_objects;
|
||||
QCheckBox* m_dump_tev_stages;
|
||||
QCheckBox* m_dump_tev_fetches;
|
||||
|
||||
QSpinBox* m_object_range_min;
|
||||
QSpinBox* m_object_range_max;
|
||||
};
|
Reference in New Issue
Block a user