1 // Copyright 2017 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #include "DolphinQt/Config/Graphics/AdvancedWidget.h"
6 
7 #include <QCheckBox>
8 #include <QGridLayout>
9 #include <QGroupBox>
10 #include <QLabel>
11 #include <QSpinBox>
12 #include <QVBoxLayout>
13 
14 #include "Core/Config/GraphicsSettings.h"
15 #include "Core/Config/SYSCONFSettings.h"
16 #include "Core/ConfigManager.h"
17 #include "Core/Core.h"
18 
19 #include "DolphinQt/Config/Graphics/GraphicsBool.h"
20 #include "DolphinQt/Config/Graphics/GraphicsChoice.h"
21 #include "DolphinQt/Config/Graphics/GraphicsInteger.h"
22 #include "DolphinQt/Config/Graphics/GraphicsWindow.h"
23 #include "DolphinQt/Settings.h"
24 
25 #include "VideoCommon/VideoConfig.h"
26 
AdvancedWidget(GraphicsWindow * parent)27 AdvancedWidget::AdvancedWidget(GraphicsWindow* parent) : GraphicsWidget(parent)
28 {
29   CreateWidgets();
30   LoadSettings();
31   ConnectWidgets();
32   AddDescriptions();
33 
34   connect(parent, &GraphicsWindow::BackendChanged, this, &AdvancedWidget::OnBackendChanged);
35   connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
36           [=](Core::State state) { OnEmulationStateChanged(state != Core::State::Uninitialized); });
37 
38   OnBackendChanged();
39   OnEmulationStateChanged(Core::GetState() != Core::State::Uninitialized);
40 }
41 
CreateWidgets()42 void AdvancedWidget::CreateWidgets()
43 {
44   auto* main_layout = new QVBoxLayout;
45 
46   // Debugging
47   auto* debugging_box = new QGroupBox(tr("Debugging"));
48   auto* debugging_layout = new QGridLayout();
49   debugging_box->setLayout(debugging_layout);
50 
51   m_enable_wireframe = new GraphicsBool(tr("Enable Wireframe"), Config::GFX_ENABLE_WIREFRAME);
52   m_show_statistics = new GraphicsBool(tr("Show Statistics"), Config::GFX_OVERLAY_STATS);
53   m_enable_format_overlay =
54       new GraphicsBool(tr("Texture Format Overlay"), Config::GFX_TEXFMT_OVERLAY_ENABLE);
55   m_enable_api_validation =
56       new GraphicsBool(tr("Enable API Validation Layers"), Config::GFX_ENABLE_VALIDATION_LAYER);
57 
58   debugging_layout->addWidget(m_enable_wireframe, 0, 0);
59   debugging_layout->addWidget(m_show_statistics, 0, 1);
60   debugging_layout->addWidget(m_enable_format_overlay, 1, 0);
61   debugging_layout->addWidget(m_enable_api_validation, 1, 1);
62 
63   // Utility
64   auto* utility_box = new QGroupBox(tr("Utility"));
65   auto* utility_layout = new QGridLayout();
66   utility_box->setLayout(utility_layout);
67 
68   m_load_custom_textures = new GraphicsBool(tr("Load Custom Textures"), Config::GFX_HIRES_TEXTURES);
69   m_prefetch_custom_textures =
70       new GraphicsBool(tr("Prefetch Custom Textures"), Config::GFX_CACHE_HIRES_TEXTURES);
71   m_dump_efb_target = new GraphicsBool(tr("Dump EFB Target"), Config::GFX_DUMP_EFB_TARGET);
72   m_disable_vram_copies =
73       new GraphicsBool(tr("Disable EFB VRAM Copies"), Config::GFX_HACK_DISABLE_COPY_TO_VRAM);
74 
75   utility_layout->addWidget(m_load_custom_textures, 0, 0);
76   utility_layout->addWidget(m_prefetch_custom_textures, 0, 1);
77 
78   utility_layout->addWidget(m_disable_vram_copies, 1, 0);
79 
80   utility_layout->addWidget(m_dump_efb_target, 1, 1);
81 
82   // Freelook
83   auto* freelook_box = new QGroupBox(tr("Free Look"));
84   auto* freelook_layout = new QGridLayout();
85   freelook_box->setLayout(freelook_layout);
86 
87   m_enable_freelook = new GraphicsBool(tr("Enable"), Config::GFX_FREE_LOOK);
88   m_freelook_control_type = new GraphicsChoice({tr("Six Axis"), tr("First Person"), tr("Orbital")},
89                                                Config::GFX_FREE_LOOK_CONTROL_TYPE);
90 
91   freelook_layout->addWidget(m_enable_freelook, 0, 0);
92   freelook_layout->addWidget(new QLabel(tr("Control Type:")), 1, 0);
93   freelook_layout->addWidget(m_freelook_control_type, 1, 1);
94 
95   // Texture dumping
96   auto* texture_dump_box = new QGroupBox(tr("Texture Dumping"));
97   auto* texture_dump_layout = new QGridLayout();
98   texture_dump_box->setLayout(texture_dump_layout);
99   m_dump_textures = new GraphicsBool(tr("Enable"), Config::GFX_DUMP_TEXTURES);
100   m_dump_base_textures = new GraphicsBool(tr("Dump Base Textures"), Config::GFX_DUMP_BASE_TEXTURES);
101   m_dump_mip_textures = new GraphicsBool(tr("Dump Mip Maps"), Config::GFX_DUMP_MIP_TEXTURES);
102 
103   texture_dump_layout->addWidget(m_dump_textures, 0, 0);
104 
105   texture_dump_layout->addWidget(m_dump_base_textures, 1, 0);
106   texture_dump_layout->addWidget(m_dump_mip_textures, 1, 1);
107 
108   // Frame dumping
109   auto* dump_box = new QGroupBox(tr("Frame Dumping"));
110   auto* dump_layout = new QGridLayout();
111   dump_box->setLayout(dump_layout);
112 
113   m_use_fullres_framedumps = new GraphicsBool(tr("Dump at Internal Resolution"),
114                                               Config::GFX_INTERNAL_RESOLUTION_FRAME_DUMPS);
115   m_dump_use_ffv1 = new GraphicsBool(tr("Use Lossless Codec (FFV1)"), Config::GFX_USE_FFV1);
116   m_dump_bitrate = new GraphicsInteger(0, 1000000, Config::GFX_BITRATE_KBPS, 1000);
117 
118   dump_layout->addWidget(m_use_fullres_framedumps, 0, 0);
119 #if defined(HAVE_FFMPEG)
120   dump_layout->addWidget(m_dump_use_ffv1, 0, 1);
121   dump_layout->addWidget(new QLabel(tr("Bitrate (kbps):")), 1, 0);
122   dump_layout->addWidget(m_dump_bitrate, 1, 1);
123 #endif
124 
125   // Misc.
126   auto* misc_box = new QGroupBox(tr("Misc"));
127   auto* misc_layout = new QGridLayout();
128   misc_box->setLayout(misc_layout);
129 
130   m_enable_cropping = new GraphicsBool(tr("Crop"), Config::GFX_CROP);
131   m_enable_prog_scan = new QCheckBox(tr("Enable Progressive Scan"));
132   m_backend_multithreading =
133       new GraphicsBool(tr("Backend Multithreading"), Config::GFX_BACKEND_MULTITHREADING);
134 
135   misc_layout->addWidget(m_enable_cropping, 0, 0);
136   misc_layout->addWidget(m_enable_prog_scan, 0, 1);
137   misc_layout->addWidget(m_backend_multithreading, 1, 0);
138 #ifdef _WIN32
139   m_borderless_fullscreen =
140       new GraphicsBool(tr("Borderless Fullscreen"), Config::GFX_BORDERLESS_FULLSCREEN);
141 
142   misc_layout->addWidget(m_borderless_fullscreen, 1, 1);
143 #endif
144 
145   // Experimental.
146   auto* experimental_box = new QGroupBox(tr("Experimental"));
147   auto* experimental_layout = new QGridLayout();
148   experimental_box->setLayout(experimental_layout);
149 
150   m_defer_efb_access_invalidation =
151       new GraphicsBool(tr("Defer EFB Cache Invalidation"), Config::GFX_HACK_EFB_DEFER_INVALIDATION);
152 
153   experimental_layout->addWidget(m_defer_efb_access_invalidation, 0, 0);
154 
155   main_layout->addWidget(debugging_box);
156   main_layout->addWidget(utility_box);
157   main_layout->addWidget(freelook_box);
158   main_layout->addWidget(texture_dump_box);
159   main_layout->addWidget(dump_box);
160   main_layout->addWidget(misc_box);
161   main_layout->addWidget(experimental_box);
162   main_layout->addStretch();
163 
164   setLayout(main_layout);
165 }
166 
ConnectWidgets()167 void AdvancedWidget::ConnectWidgets()
168 {
169   connect(m_load_custom_textures, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings);
170   connect(m_dump_use_ffv1, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings);
171   connect(m_enable_prog_scan, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings);
172   connect(m_enable_freelook, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings);
173   connect(m_dump_textures, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings);
174 }
175 
LoadSettings()176 void AdvancedWidget::LoadSettings()
177 {
178   m_prefetch_custom_textures->setEnabled(Config::Get(Config::GFX_HIRES_TEXTURES));
179   m_dump_bitrate->setEnabled(!Config::Get(Config::GFX_USE_FFV1));
180 
181   m_enable_prog_scan->setChecked(Config::Get(Config::SYSCONF_PROGRESSIVE_SCAN));
182 
183   m_freelook_control_type->setEnabled(Config::Get(Config::GFX_FREE_LOOK));
184   m_dump_mip_textures->setEnabled(Config::Get(Config::GFX_DUMP_TEXTURES));
185   m_dump_base_textures->setEnabled(Config::Get(Config::GFX_DUMP_TEXTURES));
186 }
187 
SaveSettings()188 void AdvancedWidget::SaveSettings()
189 {
190   m_prefetch_custom_textures->setEnabled(Config::Get(Config::GFX_HIRES_TEXTURES));
191   m_dump_bitrate->setEnabled(!Config::Get(Config::GFX_USE_FFV1));
192 
193   Config::SetBase(Config::SYSCONF_PROGRESSIVE_SCAN, m_enable_prog_scan->isChecked());
194 
195   m_freelook_control_type->setEnabled(Config::Get(Config::GFX_FREE_LOOK));
196   m_dump_mip_textures->setEnabled(Config::Get(Config::GFX_DUMP_TEXTURES));
197   m_dump_base_textures->setEnabled(Config::Get(Config::GFX_DUMP_TEXTURES));
198 }
199 
OnBackendChanged()200 void AdvancedWidget::OnBackendChanged()
201 {
202 }
203 
OnEmulationStateChanged(bool running)204 void AdvancedWidget::OnEmulationStateChanged(bool running)
205 {
206   m_enable_prog_scan->setEnabled(!running);
207 }
208 
AddDescriptions()209 void AdvancedWidget::AddDescriptions()
210 {
211   static const char TR_WIREFRAME_DESCRIPTION[] =
212       QT_TR_NOOP("Renders the scene as a wireframe.\n\nIf unsure, leave this unchecked.");
213   static const char TR_SHOW_STATS_DESCRIPTION[] =
214       QT_TR_NOOP("Shows various rendering statistics.\n\nIf unsure, leave this unchecked.");
215   static const char TR_TEXTURE_FORMAT_DESCRIPTION[] = QT_TR_NOOP(
216       "Modifies textures to show the format they're encoded in.\n\nMay require an emulation "
217       "reset to apply.\n\nIf unsure, leave this unchecked.");
218   static const char TR_VALIDATION_LAYER_DESCRIPTION[] =
219       QT_TR_NOOP("Enables validation of API calls made by the video backend, which may assist in "
220                  "debugging graphical issues.\n\nIf unsure, leave this unchecked.");
221   static const char TR_DUMP_TEXTURE_DESCRIPTION[] =
222       QT_TR_NOOP("Dumps decoded game textures based on the other flags to "
223                  "User/Dump/Textures/<game_id>/.\n\nIf unsure, leave "
224                  "this unchecked.");
225   static const char TR_DUMP_MIP_TEXTURE_DESCRIPTION[] = QT_TR_NOOP(
226       "Whether to dump mipmapped game textures to "
227       "User/Dump/Textures/<game_id>/.  This includes arbitrary mipmapped textures if 'Arbitrary "
228       "Mipmap Detection' is enabled in Enhancements.\n\nIf unsure, leave "
229       "this checked.");
230   static const char TR_DUMP_BASE_TEXTURE_DESCRIPTION[] = QT_TR_NOOP(
231       "Whether to dump base game textures to "
232       "User/Dump/Textures/<game_id>/.  This includes arbitrary base textures if 'Arbitrary "
233       "Mipmap Detection' is enabled in Enhancements.\n\nIf unsure, leave "
234       "this checked.");
235   static const char TR_LOAD_CUSTOM_TEXTURE_DESCRIPTION[] = QT_TR_NOOP(
236       "Loads custom textures from User/Load/Textures/<game_id>/.\n\nIf unsure, leave this "
237       "unchecked.");
238   static const char TR_CACHE_CUSTOM_TEXTURE_DESCRIPTION[] = QT_TR_NOOP(
239       "Caches custom textures to system RAM on startup.\n\nThis can require exponentially "
240       "more RAM but fixes possible stuttering.\n\nIf unsure, leave this unchecked.");
241   static const char TR_DUMP_EFB_DESCRIPTION[] = QT_TR_NOOP(
242       "Dumps the contents of EFB copies to User/Dump/Textures/.\n\nIf unsure, leave this "
243       "unchecked.");
244   static const char TR_DISABLE_VRAM_COPIES_DESCRIPTION[] =
245       QT_TR_NOOP("Disables the VRAM copy of the EFB, forcing a round-trip to RAM. Inhibits all "
246                  "upscaling.\n\nIf unsure, leave this unchecked.");
247   static const char TR_INTERNAL_RESOLUTION_FRAME_DUMPING_DESCRIPTION[] = QT_TR_NOOP(
248       "Creates frame dumps and screenshots at the internal resolution of the renderer, rather than "
249       "the size of the window it is displayed within.\n\nIf the aspect ratio is widescreen, the "
250       "output image will be scaled horizontally to preserve the vertical resolution.\n\nIf "
251       "unsure, leave this unchecked.");
252 #if defined(HAVE_FFMPEG)
253   static const char TR_USE_FFV1_DESCRIPTION[] =
254       QT_TR_NOOP("Encodes frame dumps using the FFV1 codec.\n\nIf unsure, leave this unchecked.");
255 #endif
256   static const char TR_FREE_LOOK_DESCRIPTION[] = QT_TR_NOOP(
257       "Allows manipulation of the in-game camera. Move the mouse while holding the right button "
258       "to pan or middle button to roll.\n\nUse the WASD keys while holding SHIFT to move the "
259       "camera. Press SHIFT+2 to increase speed or SHIFT+1 to decrease speed. Press SHIFT+R "
260       "to reset the camera or SHIFT+F to reset the speed.\n\nIf unsure, leave this unchecked. ");
261   static const char TR_FREE_LOOK_CONTROL_TYPE_DESCRIPTION[] = QT_TR_NOOP(
262       "Changes the in-game camera type during freelook.\n\n"
263       "Six Axis: Offers full camera control on all axes, akin to moving a spacecraft in zero "
264       "gravity. This is the most powerful freelook option but is the most challenging to use.\n"
265       "First Person: Controls the free camera similarly to a first person video game. The camera "
266       "can rotate and travel, but roll is impossible. Easy to use, but limiting.\n"
267       "Orbital: Rotates the free camera around the original camera. Has no lateral movement, only "
268       "rotation and you may zoom up to the camera's origin point.");
269   static const char TR_CROPPING_DESCRIPTION[] =
270       QT_TR_NOOP("Crops the picture from its native aspect ratio to 4:3 or "
271                  "16:9.\n\nIf unsure, leave this unchecked.");
272   static const char TR_PROGRESSIVE_SCAN_DESCRIPTION[] = QT_TR_NOOP(
273       "Enables progressive scan if supported by the emulated software. Most games don't have "
274       "any issue with this.\n\nIf unsure, leave this unchecked.");
275   static const char TR_BACKEND_MULTITHREADING_DESCRIPTION[] =
276       QT_TR_NOOP("Enables multithreaded command submission in backends where supported. Enabling "
277                  "this option may result in a performance improvement on systems with more than "
278                  "two CPU cores. Currently, this is limited to the Vulkan backend.\n\nIf unsure, "
279                  "leave this checked.");
280   static const char TR_DEFER_EFB_ACCESS_INVALIDATION_DESCRIPTION[] = QT_TR_NOOP(
281       "Defers invalidation of the EFB access cache until a GPU synchronization command "
282       "is executed. If disabled, the cache will be invalidated with every draw call. "
283       "\n\nMay improve performance in some games which rely on CPU EFB Access at the cost "
284       "of stability.\n\nIf unsure, leave this unchecked.");
285 
286 #ifdef _WIN32
287   static const char TR_BORDERLESS_FULLSCREEN_DESCRIPTION[] = QT_TR_NOOP(
288       "Implements fullscreen mode with a borderless window spanning the whole screen instead of "
289       "using exclusive mode. Allows for faster transitions between fullscreen and windowed mode, "
290       "but slightly increases input latency, makes movement less smooth and slightly decreases "
291       "performance.\n\nIf unsure, leave this unchecked.");
292 #endif
293 
294   AddDescription(m_enable_wireframe, TR_WIREFRAME_DESCRIPTION);
295   AddDescription(m_show_statistics, TR_SHOW_STATS_DESCRIPTION);
296   AddDescription(m_enable_format_overlay, TR_TEXTURE_FORMAT_DESCRIPTION);
297   AddDescription(m_enable_api_validation, TR_VALIDATION_LAYER_DESCRIPTION);
298   AddDescription(m_dump_textures, TR_DUMP_TEXTURE_DESCRIPTION);
299   AddDescription(m_dump_mip_textures, TR_DUMP_MIP_TEXTURE_DESCRIPTION);
300   AddDescription(m_dump_base_textures, TR_DUMP_BASE_TEXTURE_DESCRIPTION);
301   AddDescription(m_load_custom_textures, TR_LOAD_CUSTOM_TEXTURE_DESCRIPTION);
302   AddDescription(m_prefetch_custom_textures, TR_CACHE_CUSTOM_TEXTURE_DESCRIPTION);
303   AddDescription(m_dump_efb_target, TR_DUMP_EFB_DESCRIPTION);
304   AddDescription(m_disable_vram_copies, TR_DISABLE_VRAM_COPIES_DESCRIPTION);
305   AddDescription(m_use_fullres_framedumps, TR_INTERNAL_RESOLUTION_FRAME_DUMPING_DESCRIPTION);
306 #ifdef HAVE_FFMPEG
307   AddDescription(m_dump_use_ffv1, TR_USE_FFV1_DESCRIPTION);
308 #endif
309   AddDescription(m_enable_cropping, TR_CROPPING_DESCRIPTION);
310   AddDescription(m_enable_prog_scan, TR_PROGRESSIVE_SCAN_DESCRIPTION);
311   AddDescription(m_enable_freelook, TR_FREE_LOOK_DESCRIPTION);
312   AddDescription(m_freelook_control_type, TR_FREE_LOOK_CONTROL_TYPE_DESCRIPTION);
313   AddDescription(m_backend_multithreading, TR_BACKEND_MULTITHREADING_DESCRIPTION);
314 #ifdef _WIN32
315   AddDescription(m_borderless_fullscreen, TR_BORDERLESS_FULLSCREEN_DESCRIPTION);
316 #endif
317   AddDescription(m_defer_efb_access_invalidation, TR_DEFER_EFB_ACCESS_INVALIDATION_DESCRIPTION);
318 }
319