mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-05-12 15:49:39 -06:00
video_core: Stereo Settings Improvements: Full Width SBS, Swap Eyes, Select which display(s) to render on (#1212)
This commit is contained in:
parent
48cbeb0993
commit
4bdcf342b6
@ -63,4 +63,37 @@ enum class SecondaryDisplayLayout(val int: Int) {
|
||||
return entries.firstOrNull { it.int == int } ?: NONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class StereoWhichDisplay(val int: Int) {
|
||||
// These must match what is defined in src/common/settings.h
|
||||
|
||||
NONE(0), // equivalent to StereoRenderOption = Off
|
||||
BOTH(1),
|
||||
PRIMARY_ONLY(2),
|
||||
SECONDARY_ONLY(3);
|
||||
|
||||
companion object {
|
||||
fun from(int: Int): StereoWhichDisplay {
|
||||
return entries.firstOrNull { it.int == int } ?: NONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class StereoMode(val int: Int) {
|
||||
// These must match what is defined in src/common/settings.h
|
||||
|
||||
OFF(0),
|
||||
SIDE_BY_SIDE(1),
|
||||
SIDE_BY_SIDE_FULL(2),
|
||||
ANAGLYPH(3),
|
||||
INTERLACED(4),
|
||||
REVERSE_INTERLACED (5),
|
||||
CARDBOARD_VR (6);
|
||||
|
||||
companion object {
|
||||
fun from(int: Int): StereoMode {
|
||||
return entries.firstOrNull { it.int == int } ?: OFF
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -19,6 +19,7 @@ enum class BooleanSetting(
|
||||
INSTANT_DEBUG_LOG("instant_debug_log", Settings.SECTION_DEBUG, false),
|
||||
ENABLE_RPC_SERVER("enable_rpc_server", Settings.SECTION_DEBUG, false),
|
||||
CUSTOM_LAYOUT("custom_layout",Settings.SECTION_LAYOUT,false),
|
||||
SWAP_EYES_3D("swap_eyes_3d",Settings.SECTION_RENDERER,false),
|
||||
PERF_OVERLAY_ENABLE("performance_overlay_enable", Settings.SECTION_LAYOUT, false),
|
||||
PERF_OVERLAY_SHOW_FPS("performance_overlay_show_fps", Settings.SECTION_LAYOUT, true),
|
||||
PERF_OVERLAY_SHOW_FRAMETIME("performance_overlay_show_frame_time", Settings.SECTION_LAYOUT, false),
|
||||
@ -87,7 +88,8 @@ enum class BooleanSetting(
|
||||
USE_ARTIC_BASE_CONTROLLER,
|
||||
COMPRESS_INSTALLED_CIA_CONTENT,
|
||||
ANDROID_HIDE_IMAGES,
|
||||
PERF_OVERLAY_ENABLE // Works in overlay options, but not from the settings menu
|
||||
PERF_OVERLAY_ENABLE, // Works in overlay options, but not from the settings menu
|
||||
APPLY_REGION_FREE_PATCH
|
||||
)
|
||||
|
||||
fun from(key: String): BooleanSetting? =
|
||||
|
||||
@ -17,7 +17,7 @@ enum class IntSetting(
|
||||
CAMERA_OUTER_RIGHT_FLIP("camera_outer_right_flip", Settings.SECTION_CAMERA, 0),
|
||||
GRAPHICS_API("graphics_api", Settings.SECTION_RENDERER, 1),
|
||||
RESOLUTION_FACTOR("resolution_factor", Settings.SECTION_RENDERER, 1),
|
||||
STEREOSCOPIC_3D_MODE("render_3d", Settings.SECTION_RENDERER, 0),
|
||||
STEREOSCOPIC_3D_MODE("render_3d", Settings.SECTION_RENDERER, 2),
|
||||
STEREOSCOPIC_3D_DEPTH("factor_3d", Settings.SECTION_RENDERER, 0),
|
||||
STEPS_PER_HOUR("steps_per_hour", Settings.SECTION_SYSTEM, 0),
|
||||
CARDBOARD_SCREEN_SIZE("cardboard_screen_size", Settings.SECTION_LAYOUT, 85),
|
||||
@ -53,6 +53,7 @@ enum class IntSetting(
|
||||
ORIENTATION_OPTION("screen_orientation", Settings.SECTION_LAYOUT, 2),
|
||||
TURBO_LIMIT("turbo_limit", Settings.SECTION_CORE, 200),
|
||||
PERFORMANCE_OVERLAY_POSITION("performance_overlay_position", Settings.SECTION_LAYOUT, 0),
|
||||
RENDER_3D_WHICH_DISPLAY("render_3d_which_display",Settings.SECTION_RENDERER,0),
|
||||
ASPECT_RATIO("aspect_ratio", Settings.SECTION_LAYOUT, 0);
|
||||
|
||||
override var int: Int = defaultValue
|
||||
|
||||
@ -16,6 +16,9 @@ import androidx.preference.PreferenceManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.citra.citra_emu.CitraApplication
|
||||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.display.ScreenLayout
|
||||
import org.citra.citra_emu.display.StereoMode
|
||||
import org.citra.citra_emu.display.StereoWhichDisplay
|
||||
import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractIntSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractSetting
|
||||
@ -948,17 +951,30 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
)
|
||||
|
||||
add(HeaderSetting(R.string.stereoscopy))
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.RENDER_3D_WHICH_DISPLAY,
|
||||
R.string.render_3d_which_display,
|
||||
R.string.render_3d_which_display_description,
|
||||
R.array.render3dWhichDisplay,
|
||||
R.array.render3dDisplayValues,
|
||||
IntSetting.RENDER_3D_WHICH_DISPLAY.key,
|
||||
IntSetting.RENDER_3D_WHICH_DISPLAY.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.STEREOSCOPIC_3D_MODE,
|
||||
R.string.render3d,
|
||||
0,
|
||||
R.string.render3d_description,
|
||||
R.array.render3dModes,
|
||||
R.array.render3dValues,
|
||||
IntSetting.STEREOSCOPIC_3D_MODE.key,
|
||||
IntSetting.STEREOSCOPIC_3D_MODE.defaultValue
|
||||
IntSetting.STEREOSCOPIC_3D_MODE.defaultValue,
|
||||
isEnabled = IntSetting.RENDER_3D_WHICH_DISPLAY.int != StereoWhichDisplay.NONE.int
|
||||
)
|
||||
)
|
||||
|
||||
add(
|
||||
SliderSetting(
|
||||
IntSetting.STEREOSCOPIC_3D_DEPTH,
|
||||
@ -981,6 +997,17 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
)
|
||||
)
|
||||
|
||||
add(
|
||||
SwitchSetting(
|
||||
BooleanSetting.SWAP_EYES_3D,
|
||||
R.string.swap_eyes_3d,
|
||||
R.string.swap_eyes_3d_description,
|
||||
BooleanSetting.SWAP_EYES_3D.key,
|
||||
BooleanSetting.SWAP_EYES_3D.defaultValue,
|
||||
isEnabled = IntSetting.RENDER_3D_WHICH_DISPLAY.int != StereoWhichDisplay.NONE.int
|
||||
)
|
||||
)
|
||||
|
||||
add(HeaderSetting(R.string.cardboard_vr))
|
||||
add(
|
||||
SliderSetting(
|
||||
@ -991,7 +1018,8 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
100,
|
||||
"%",
|
||||
IntSetting.CARDBOARD_SCREEN_SIZE.key,
|
||||
IntSetting.CARDBOARD_SCREEN_SIZE.defaultValue.toFloat()
|
||||
IntSetting.CARDBOARD_SCREEN_SIZE.defaultValue.toFloat(),
|
||||
isEnabled = IntSetting.STEREOSCOPIC_3D_MODE.int == StereoMode.CARDBOARD_VR.int
|
||||
)
|
||||
)
|
||||
add(
|
||||
@ -1003,7 +1031,8 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
100,
|
||||
"%",
|
||||
IntSetting.CARDBOARD_X_SHIFT.key,
|
||||
IntSetting.CARDBOARD_X_SHIFT.defaultValue.toFloat()
|
||||
IntSetting.CARDBOARD_X_SHIFT.defaultValue.toFloat(),
|
||||
isEnabled = IntSetting.STEREOSCOPIC_3D_MODE.int == StereoMode.CARDBOARD_VR.int
|
||||
)
|
||||
)
|
||||
add(
|
||||
@ -1015,7 +1044,8 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
100,
|
||||
"%",
|
||||
IntSetting.CARDBOARD_Y_SHIFT.key,
|
||||
IntSetting.CARDBOARD_Y_SHIFT.defaultValue.toFloat()
|
||||
IntSetting.CARDBOARD_Y_SHIFT.defaultValue.toFloat(),
|
||||
isEnabled = IntSetting.STEREOSCOPIC_3D_MODE.int == StereoMode.CARDBOARD_VR.int
|
||||
)
|
||||
)
|
||||
|
||||
@ -1149,7 +1179,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
R.array.aspectRatioValues,
|
||||
IntSetting.ASPECT_RATIO.key,
|
||||
IntSetting.ASPECT_RATIO.defaultValue,
|
||||
isEnabled = IntSetting.SCREEN_LAYOUT.int == 1,
|
||||
isEnabled = IntSetting.SCREEN_LAYOUT.int == ScreenLayout.SINGLE_SCREEN.int,
|
||||
)
|
||||
)
|
||||
add(
|
||||
@ -1197,7 +1227,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
"%",
|
||||
FloatSetting.SECOND_SCREEN_OPACITY.key,
|
||||
FloatSetting.SECOND_SCREEN_OPACITY.defaultValue,
|
||||
isEnabled = IntSetting.SCREEN_LAYOUT.int == 5
|
||||
isEnabled = IntSetting.SCREEN_LAYOUT.int == ScreenLayout.CUSTOM_LAYOUT.int
|
||||
)
|
||||
)
|
||||
add(HeaderSetting(R.string.bg_color, R.string.bg_color_description))
|
||||
|
||||
@ -175,7 +175,8 @@ void Config::ReadValues() {
|
||||
ReadSetting("Renderer", Settings::values.custom_second_layer_opacity);
|
||||
ReadSetting("Renderer", Settings::values.delay_game_render_thread_us);
|
||||
ReadSetting("Renderer", Settings::values.disable_right_eye_render);
|
||||
|
||||
ReadSetting("Renderer", Settings::values.swap_eyes_3d);
|
||||
ReadSetting("Renderer", Settings::values.render_3d_which_display);
|
||||
// Layout
|
||||
// Somewhat inelegant solution to ensure layout value is between 0 and 5 on read
|
||||
// since older config files may have other values
|
||||
|
||||
@ -170,13 +170,23 @@ bg_green =
|
||||
custom_second_layer_opacity =
|
||||
|
||||
# Whether and how Stereoscopic 3D should be rendered
|
||||
# 0 (default): Off, 1: Side by Side, 2: Reverse Side by Side, 3: Anaglyph, 4: Interlaced, 5: Reverse Interlaced, 6: Cardboard VR
|
||||
# 0: Off, 1: Half Width Side by Side, 2 (default): Full Width Side by Side, 3: Anaglyph, 4: Interlaced, 5: Reverse Interlaced, 6: Cardboard VR
|
||||
# 0 is no longer supported in the interface, as using render_3d_which_display = 0 has the same effect, but supported here for backwards compatibility
|
||||
render_3d =
|
||||
|
||||
# Change 3D Intensity
|
||||
# 0 - 255: Intensity. 0 (default)
|
||||
factor_3d =
|
||||
|
||||
# Swap Eyes in 3d
|
||||
# true: Swap eyes, false (default): Do not swap eyes
|
||||
swap_eyes_3d =
|
||||
|
||||
# Which Display to render 3d mode to
|
||||
# 0 (default) - None. Equivalent to render_3d=0
|
||||
# 1: Both, 2: Primary Only, 3: Secondary Only
|
||||
render_3d_which_display =
|
||||
|
||||
# The name of the post processing shader to apply.
|
||||
# Loaded from shaders if render_3d is off or side by side.
|
||||
pp_shader_name =
|
||||
|
||||
@ -238,9 +238,8 @@
|
||||
</integer-array>
|
||||
|
||||
<string-array name="render3dModes">
|
||||
<item>@string/off</item>
|
||||
<item>@string/side_by_side</item>
|
||||
<item>@string/reverse_side_by_side</item>
|
||||
<item>@string/side_by_side_full</item>
|
||||
<item>@string/anaglyph</item>
|
||||
<item>@string/interlaced</item>
|
||||
<item>@string/reverse_interlaced</item>
|
||||
@ -248,7 +247,6 @@
|
||||
</string-array>
|
||||
|
||||
<integer-array name="render3dValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
@ -257,6 +255,20 @@
|
||||
<item>6</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="render3dWhichDisplay">
|
||||
<item>@string/off</item>
|
||||
<item>@string/render_3d_which_display_both</item>
|
||||
<item>@string/render_3d_which_display_primary</item>
|
||||
<item>@string/render_3d_which_display_secondary</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="render3dDisplayValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="graphicsApiNames">
|
||||
<item>@string/opengles</item>
|
||||
<item>@string/vulkan</item>
|
||||
|
||||
@ -289,10 +289,18 @@
|
||||
<string name="debug_warning">Warning: Modifying these settings will slow emulation</string>
|
||||
<string name="stereoscopy">Stereoscopy</string>
|
||||
<string name="render3d">Stereoscopic 3D Mode</string>
|
||||
<string name="render3d_description">Choose the stereoscopic 3D mode for 3D rendering. Side by Side modes are most common in modern use. Anaglyph and Interlaced modes will always apply to all connected displays.</string>
|
||||
<string name="factor3d">Depth</string>
|
||||
<string name="factor3d_description">Specifies the value of the 3D slider. This should be set to higher than 0% when Stereoscopic 3D is enabled.\nNote: Depth values over 100% are not possible on real hardware and may cause graphical issues</string>
|
||||
<string name="disable_right_eye_render">Disable Right Eye Render</string>
|
||||
<string name="disable_right_eye_render_description">Greatly improves performance in some applications, but can cause flickering in others.</string>
|
||||
<string name="swap_eyes_3d">Swap Eyes</string>
|
||||
<string name="swap_eyes_3d_description">Swaps which eye is shown in which side. Combined with Side by Side mode makes it possible to see 3D by crossing your eyes!</string>
|
||||
<string name="render_3d_which_display">Render Stereoscopic 3D</string>
|
||||
<string name="render_3d_which_display_description">Whether to enable stereoscopic 3D, and on which displays. The single display options are only relevant when multiple displays are connected.</string>
|
||||
<string name="render_3d_which_display_both">On (All Displays)</string>
|
||||
<string name="render_3d_which_display_primary">On (Primary Display Only)</string>
|
||||
<string name="render_3d_which_display_secondary">On (Secondary Display Only)</string>
|
||||
<string name="cardboard_vr">Cardboard VR</string>
|
||||
<string name="cardboard_screen_size">Cardboard Screen Size</string>
|
||||
<string name="cardboard_screen_size_description">Scales the screen to a percentage of its original size.</string>
|
||||
@ -723,7 +731,7 @@
|
||||
|
||||
<!-- Render 3D modes -->
|
||||
<string name="side_by_side">Side by Side</string>
|
||||
<string name="reverse_side_by_side">Reverse Side by Side</string>
|
||||
<string name="side_by_side_full">Side by Side Full Width</string>
|
||||
<string name="anaglyph">Anaglyph</string>
|
||||
<string name="interlaced">Interlaced</string>
|
||||
<string name="reverse_interlaced">Reverse Interlaced</string>
|
||||
|
||||
@ -517,6 +517,8 @@ void QtConfig::ReadLayoutValues() {
|
||||
|
||||
ReadGlobalSetting(Settings::values.render_3d);
|
||||
ReadGlobalSetting(Settings::values.factor_3d);
|
||||
ReadGlobalSetting(Settings::values.swap_eyes_3d);
|
||||
ReadGlobalSetting(Settings::values.render_3d_which_display);
|
||||
ReadGlobalSetting(Settings::values.filter_mode);
|
||||
ReadGlobalSetting(Settings::values.pp_shader_name);
|
||||
ReadGlobalSetting(Settings::values.anaglyph_shader_name);
|
||||
@ -1083,6 +1085,8 @@ void QtConfig::SaveLayoutValues() {
|
||||
|
||||
WriteGlobalSetting(Settings::values.render_3d);
|
||||
WriteGlobalSetting(Settings::values.factor_3d);
|
||||
WriteGlobalSetting(Settings::values.swap_eyes_3d);
|
||||
WriteGlobalSetting(Settings::values.render_3d_which_display);
|
||||
WriteGlobalSetting(Settings::values.filter_mode);
|
||||
WriteGlobalSetting(Settings::values.pp_shader_name);
|
||||
WriteGlobalSetting(Settings::values.anaglyph_shader_name);
|
||||
|
||||
@ -57,6 +57,7 @@ void ConfigureEnhancements::SetConfiguration() {
|
||||
|
||||
ui->render_3d_combobox->setCurrentIndex(
|
||||
static_cast<int>(Settings::values.render_3d.GetValue()));
|
||||
ui->swap_eyes_3d->setChecked(Settings::values.swap_eyes_3d.GetValue());
|
||||
ui->factor_3d->setValue(Settings::values.factor_3d.GetValue());
|
||||
ui->mono_rendering_eye->setCurrentIndex(
|
||||
static_cast<int>(Settings::values.mono_render_option.GetValue()));
|
||||
@ -111,6 +112,7 @@ void ConfigureEnhancements::ApplyConfiguration() {
|
||||
ui->resolution_factor_combobox);
|
||||
Settings::values.render_3d =
|
||||
static_cast<Settings::StereoRenderOption>(ui->render_3d_combobox->currentIndex());
|
||||
Settings::values.swap_eyes_3d = ui->swap_eyes_3d->isChecked();
|
||||
Settings::values.factor_3d = ui->factor_3d->value();
|
||||
Settings::values.mono_render_option =
|
||||
static_cast<Settings::MonoRenderOption>(ui->mono_rendering_eye->currentIndex());
|
||||
|
||||
@ -113,7 +113,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="toggle_linear_filter">
|
||||
<property name="text">
|
||||
<string>Enable linear filtering</string>
|
||||
<string>Enable Linear Filtering</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -236,7 +236,7 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Reverse Side by Side</string>
|
||||
<string>Side by Side Full Width</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
@ -318,14 +318,21 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="disable_right_eye_render">
|
||||
<property name="text">
|
||||
<string>Disable right eye rendering</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Disable Right Eye Rendering</p><p>Disables rendering the right eye image when not using stereoscopic mode. Greatly improves performance in some applications, but can cause flickering in others.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="disable_right_eye_render">
|
||||
<property name="text">
|
||||
<string>Disable Right Eye Rendering</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Disable Right Eye Rendering</p><p>Disables rendering the right eye image when not using stereoscopic mode. Greatly improves performance in some applications, but can cause flickering in others.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="swap_eyes_3d">
|
||||
<property name="text">
|
||||
<string>Swap Eyes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
@ -163,6 +163,10 @@ render_3d =
|
||||
# 0 - 100: Intensity. 0 (default)
|
||||
factor_3d =
|
||||
|
||||
# Swap Eyes in 3D
|
||||
# true or false (default)
|
||||
swap_eyes_3d =
|
||||
|
||||
# Change Default Eye to Render When in Monoscopic Mode
|
||||
# 0 (default): Left, 1: Right
|
||||
mono_render_option =
|
||||
|
||||
@ -108,6 +108,9 @@ void LogSettings() {
|
||||
log_setting("Renderer_DisableRightEyeRender", values.disable_right_eye_render.GetValue());
|
||||
log_setting("Stereoscopy_Render3d", values.render_3d.GetValue());
|
||||
log_setting("Stereoscopy_Factor3d", values.factor_3d.GetValue());
|
||||
log_setting("Stereoscopy_Swap_Eyes", values.swap_eyes_3d.GetValue());
|
||||
log_setting("Stereoscopy_Render_3d_to_which_display",
|
||||
values.render_3d_which_display.GetValue());
|
||||
log_setting("Stereoscopy_MonoRenderOption", values.mono_render_option.GetValue());
|
||||
if (values.render_3d.GetValue() == StereoRenderOption::Anaglyph) {
|
||||
log_setting("Renderer_AnaglyphShader", values.anaglyph_shader_name.GetValue());
|
||||
@ -219,6 +222,7 @@ void RestoreGlobalState(bool is_powered_on) {
|
||||
values.bg_green.SetGlobal(true);
|
||||
values.bg_blue.SetGlobal(true);
|
||||
values.render_3d.SetGlobal(true);
|
||||
values.swap_eyes_3d.SetGlobal(true);
|
||||
values.factor_3d.SetGlobal(true);
|
||||
values.filter_mode.SetGlobal(true);
|
||||
values.pp_shader_name.SetGlobal(true);
|
||||
|
||||
@ -72,7 +72,7 @@ enum class SmallScreenPosition : u32 {
|
||||
enum class StereoRenderOption : u32 {
|
||||
Off = 0,
|
||||
SideBySide = 1,
|
||||
ReverseSideBySide = 2,
|
||||
SideBySideFull = 2,
|
||||
Anaglyph = 3,
|
||||
Interlaced = 4,
|
||||
ReverseInterlaced = 5,
|
||||
@ -86,6 +86,14 @@ enum class MonoRenderOption : u32 {
|
||||
RightEye = 1,
|
||||
};
|
||||
|
||||
// on android, which displays to render stereo mode to
|
||||
enum class StereoWhichDisplay : u32 {
|
||||
None = 0, // equivalent to StereoRenderOption = Off
|
||||
Both = 1,
|
||||
PrimaryOnly = 2,
|
||||
SecondaryOnly = 3
|
||||
};
|
||||
|
||||
enum class AudioEmulation : u32 {
|
||||
HLE = 0,
|
||||
LLE = 1,
|
||||
@ -562,6 +570,10 @@ struct Values {
|
||||
|
||||
SwitchableSetting<StereoRenderOption> render_3d{StereoRenderOption::Off, "render_3d"};
|
||||
SwitchableSetting<u32> factor_3d{0, "factor_3d"};
|
||||
SwitchableSetting<bool> swap_eyes_3d{false, "swap_eyes_3d"};
|
||||
|
||||
SwitchableSetting<StereoWhichDisplay> render_3d_which_display{StereoWhichDisplay::None,
|
||||
"render_3d_which_display"};
|
||||
SwitchableSetting<MonoRenderOption> mono_render_option{MonoRenderOption::LeftEye,
|
||||
"mono_render_option"};
|
||||
|
||||
|
||||
@ -25,9 +25,8 @@ public:
|
||||
std::mutex mutex;
|
||||
|
||||
bool touch_pressed = false; ///< True if touchpad area is currently pressed, otherwise false
|
||||
|
||||
float touch_x = 0.0f; ///< Touchpad X-position
|
||||
float touch_y = 0.0f; ///< Touchpad Y-position
|
||||
float touch_x = 0.0f; ///< Touchpad X-position
|
||||
float touch_y = 0.0f; ///< Touchpad Y-position
|
||||
|
||||
private:
|
||||
class Device : public Input::TouchDevice {
|
||||
@ -56,24 +55,44 @@ EmuWindow::EmuWindow(bool is_secondary_) : is_secondary{is_secondary_} {
|
||||
|
||||
EmuWindow::~EmuWindow() = default;
|
||||
|
||||
Settings::StereoRenderOption EmuWindow::get3DMode() const {
|
||||
Settings::StereoRenderOption render_3d_mode = Settings::values.render_3d.GetValue();
|
||||
#ifndef ANDROID
|
||||
// on desktop, if separate windows and this is the bottom screen, then no stereo
|
||||
if (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows &&
|
||||
((!is_secondary && Settings::values.swap_screen.GetValue()) ||
|
||||
(is_secondary && !Settings::values.swap_screen.GetValue()))) {
|
||||
render_3d_mode = Settings::StereoRenderOption::Off;
|
||||
}
|
||||
#else
|
||||
// adjust the StereoRenderOption setting to Off if appropriate on mobile
|
||||
Settings::StereoWhichDisplay whichDisplay = Settings::values.render_3d_which_display.GetValue();
|
||||
if (whichDisplay == Settings::StereoWhichDisplay::None ||
|
||||
whichDisplay == Settings::StereoWhichDisplay::PrimaryOnly && is_secondary ||
|
||||
whichDisplay == Settings::StereoWhichDisplay::SecondaryOnly && !is_secondary) {
|
||||
render_3d_mode = Settings::StereoRenderOption::Off;
|
||||
}
|
||||
#endif
|
||||
return render_3d_mode;
|
||||
}
|
||||
|
||||
bool EmuWindow::IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigned framebuffer_x,
|
||||
unsigned framebuffer_y) {
|
||||
#ifndef ANDROID
|
||||
// If separate windows and the touch is in the primary (top) screen, ignore it.
|
||||
if (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows &&
|
||||
!is_secondary && !Settings::values.swap_screen.GetValue()) {
|
||||
((!is_secondary && !Settings::values.swap_screen.GetValue()) ||
|
||||
(is_secondary && Settings::values.swap_screen.GetValue()))) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
Settings::StereoRenderOption render_3d_mode = get3DMode();
|
||||
|
||||
if (!layout.bottom_screen_enabled) {
|
||||
return false;
|
||||
if (framebuffer_x > layout.width / 2 &&
|
||||
render_3d_mode == Settings::StereoRenderOption::SideBySideFull) {
|
||||
framebuffer_x = static_cast<unsigned>(framebuffer_x - layout.width / 2);
|
||||
}
|
||||
|
||||
Settings::StereoRenderOption render_3d_mode = Settings::values.render_3d.GetValue();
|
||||
|
||||
if (render_3d_mode == Settings::StereoRenderOption::SideBySide ||
|
||||
render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) {
|
||||
if (render_3d_mode == Settings::StereoRenderOption::SideBySide) {
|
||||
return (framebuffer_y >= layout.bottom_screen.top &&
|
||||
framebuffer_y < layout.bottom_screen.bottom &&
|
||||
((framebuffer_x >= layout.bottom_screen.left / 2 &&
|
||||
@ -97,25 +116,19 @@ bool EmuWindow::IsWithinTouchscreen(const Layout::FramebufferLayout& layout, uns
|
||||
}
|
||||
|
||||
std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const {
|
||||
Settings::StereoRenderOption render_3d_mode = Settings::values.render_3d.GetValue();
|
||||
bool separate_win = false;
|
||||
#ifndef ANDROID
|
||||
separate_win =
|
||||
(Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows);
|
||||
#endif
|
||||
|
||||
Settings::StereoRenderOption render_3d_mode = get3DMode();
|
||||
|
||||
if (new_x >= framebuffer_layout.width / 2) {
|
||||
if ((render_3d_mode == Settings::StereoRenderOption::SideBySide ||
|
||||
render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) &&
|
||||
!separate_win)
|
||||
if (render_3d_mode == Settings::StereoRenderOption::SideBySide ||
|
||||
render_3d_mode == Settings::StereoRenderOption::SideBySideFull)
|
||||
new_x -= framebuffer_layout.width / 2;
|
||||
else if (render_3d_mode == Settings::StereoRenderOption::CardboardVR)
|
||||
new_x -=
|
||||
(framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2);
|
||||
}
|
||||
if ((render_3d_mode == Settings::StereoRenderOption::SideBySide ||
|
||||
render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) &&
|
||||
!separate_win) {
|
||||
|
||||
if (render_3d_mode == Settings::StereoRenderOption::SideBySide) {
|
||||
new_x = std::max(new_x, framebuffer_layout.bottom_screen.left / 2);
|
||||
new_x = std::min(new_x, framebuffer_layout.bottom_screen.right / 2 - 1);
|
||||
} else {
|
||||
@ -140,29 +153,22 @@ void EmuWindow::CreateTouchState() {
|
||||
}
|
||||
|
||||
bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
|
||||
Settings::StereoRenderOption render_3d_mode = Settings::values.render_3d.GetValue();
|
||||
bool separate_win = false;
|
||||
#ifndef ANDROID
|
||||
separate_win =
|
||||
(Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows);
|
||||
#endif
|
||||
|
||||
if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y))
|
||||
return false;
|
||||
Settings::StereoRenderOption render_3d_mode = get3DMode();
|
||||
|
||||
if (framebuffer_x >= framebuffer_layout.width / 2) {
|
||||
if ((render_3d_mode == Settings::StereoRenderOption::SideBySide ||
|
||||
render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) &&
|
||||
!separate_win)
|
||||
if (render_3d_mode == Settings::StereoRenderOption::SideBySide ||
|
||||
render_3d_mode == Settings::StereoRenderOption::SideBySideFull)
|
||||
framebuffer_x -= framebuffer_layout.width / 2;
|
||||
else if (render_3d_mode == Settings::StereoRenderOption::CardboardVR)
|
||||
framebuffer_x -=
|
||||
(framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2);
|
||||
}
|
||||
|
||||
std::scoped_lock guard(touch_state->mutex);
|
||||
if ((render_3d_mode == Settings::StereoRenderOption::SideBySide ||
|
||||
render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) &&
|
||||
!separate_win) {
|
||||
|
||||
if (render_3d_mode == Settings::StereoRenderOption::SideBySide) {
|
||||
touch_state->touch_x =
|
||||
static_cast<float>(framebuffer_x - framebuffer_layout.bottom_screen.left / 2) /
|
||||
(framebuffer_layout.bottom_screen.right / 2 -
|
||||
@ -204,8 +210,13 @@ void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) {
|
||||
|
||||
void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_portrait_mode) {
|
||||
Layout::FramebufferLayout layout;
|
||||
|
||||
const Settings::LayoutOption layout_option = Settings::values.layout_option.GetValue();
|
||||
const Settings::StereoRenderOption stereo_option = get3DMode();
|
||||
bool render_full_stereo = (stereo_option == Settings::StereoRenderOption::SideBySideFull);
|
||||
bool is_bottom = is_secondary;
|
||||
if (Settings::values.swap_screen.GetValue())
|
||||
is_bottom = !is_bottom;
|
||||
|
||||
const Settings::PortraitLayoutOption portrait_layout_option =
|
||||
Settings::values.portrait_layout_option.GetValue();
|
||||
const auto min_size = is_portrait_mode
|
||||
@ -215,6 +226,9 @@ void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_po
|
||||
|
||||
width = std::max(width, min_size.first);
|
||||
height = std::max(height, min_size.second);
|
||||
if (render_full_stereo) {
|
||||
width = width / 2;
|
||||
}
|
||||
if (is_portrait_mode) {
|
||||
switch (portrait_layout_option) {
|
||||
case Settings::PortraitLayoutOption::PortraitTopFullWidth:
|
||||
@ -280,11 +294,16 @@ void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_po
|
||||
layout = Layout::AndroidSecondaryLayout(width, height);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (render_full_stereo) {
|
||||
layout.width = width * 2;
|
||||
}
|
||||
UpdateMinimumWindowSize(min_size);
|
||||
|
||||
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) {
|
||||
layout = Layout::GetCardboardSettings(layout);
|
||||
}
|
||||
layout.render_3d_mode = stereo_option;
|
||||
NotifyFramebufferLayoutChanged(layout);
|
||||
}
|
||||
|
||||
|
||||
@ -258,6 +258,8 @@ public:
|
||||
return is_secondary;
|
||||
}
|
||||
|
||||
Settings::StereoRenderOption get3DMode() const;
|
||||
|
||||
protected:
|
||||
EmuWindow();
|
||||
EmuWindow(bool is_secondary);
|
||||
|
||||
@ -79,7 +79,7 @@ FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool swapped, bool up
|
||||
|
||||
// TODO: This is kind of gross, make it platform agnostic. -OS
|
||||
#ifdef ANDROID
|
||||
const float window_aspect_ratio = static_cast<float>(height) / static_cast<float>(width);
|
||||
const float window_aspect_ratio = static_cast<float>(height) / width;
|
||||
const auto aspect_ratio_setting = Settings::values.aspect_ratio.GetValue();
|
||||
|
||||
float emulation_aspect_ratio = (swapped) ? BOT_SCREEN_ASPECT_RATIO : TOP_SCREEN_ASPECT_RATIO;
|
||||
@ -413,53 +413,56 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
|
||||
bool is_portrait) {
|
||||
u32 width, height, gap;
|
||||
gap = (int)(Settings::values.screen_gap.GetValue()) * res_scale;
|
||||
|
||||
FramebufferLayout layout;
|
||||
if (is_portrait) {
|
||||
auto layout_option = Settings::values.portrait_layout_option.GetValue();
|
||||
switch (layout_option) {
|
||||
case Settings::PortraitLayoutOption::PortraitCustomLayout:
|
||||
return CustomFrameLayout(
|
||||
std::max(Settings::values.custom_portrait_top_x.GetValue() +
|
||||
Settings::values.custom_portrait_top_width.GetValue(),
|
||||
Settings::values.custom_portrait_bottom_x.GetValue() +
|
||||
Settings::values.custom_portrait_bottom_width.GetValue()),
|
||||
std::max(Settings::values.custom_portrait_top_y.GetValue() +
|
||||
Settings::values.custom_portrait_top_height.GetValue(),
|
||||
Settings::values.custom_portrait_bottom_y.GetValue() +
|
||||
Settings::values.custom_portrait_bottom_height.GetValue()),
|
||||
Settings::values.swap_screen.GetValue(), is_portrait);
|
||||
width = std::max(Settings::values.custom_portrait_top_x.GetValue() +
|
||||
Settings::values.custom_portrait_top_width.GetValue(),
|
||||
Settings::values.custom_portrait_bottom_x.GetValue() +
|
||||
Settings::values.custom_portrait_bottom_width.GetValue());
|
||||
height = std::max(Settings::values.custom_portrait_top_y.GetValue() +
|
||||
Settings::values.custom_portrait_top_height.GetValue(),
|
||||
Settings::values.custom_portrait_bottom_y.GetValue() +
|
||||
Settings::values.custom_portrait_bottom_height.GetValue());
|
||||
layout = CustomFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||
is_portrait);
|
||||
|
||||
break;
|
||||
case Settings::PortraitLayoutOption::PortraitTopFullWidth:
|
||||
width = Core::kScreenTopWidth * res_scale;
|
||||
// clang-format off
|
||||
height = (static_cast<int>(Core::kScreenTopHeight + Core::kScreenBottomHeight * 1.25) *
|
||||
res_scale) + gap;
|
||||
// clang-format on
|
||||
return PortraitTopFullFrameLayout(width, height,
|
||||
Settings::values.swap_screen.GetValue(),
|
||||
Settings::values.upright_screen.GetValue());
|
||||
layout =
|
||||
PortraitTopFullFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||
Settings::values.upright_screen.GetValue());
|
||||
break;
|
||||
case Settings::PortraitLayoutOption::PortraitOriginal:
|
||||
width = Core::kScreenTopWidth * res_scale;
|
||||
height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale;
|
||||
return PortraitOriginalLayout(width, height, Settings::values.swap_screen.GetValue());
|
||||
layout = PortraitOriginalLayout(width, height, Settings::values.swap_screen.GetValue());
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
auto layout_option = Settings::values.layout_option.GetValue();
|
||||
switch (layout_option) {
|
||||
case Settings::LayoutOption::CustomLayout:
|
||||
return CustomFrameLayout(std::max(Settings::values.custom_top_x.GetValue() +
|
||||
Settings::values.custom_top_width.GetValue(),
|
||||
Settings::values.custom_bottom_x.GetValue() +
|
||||
Settings::values.custom_bottom_width.GetValue()),
|
||||
std::max(Settings::values.custom_top_y.GetValue() +
|
||||
Settings::values.custom_top_height.GetValue(),
|
||||
Settings::values.custom_bottom_y.GetValue() +
|
||||
Settings::values.custom_bottom_height.GetValue()),
|
||||
Settings::values.swap_screen.GetValue(), is_portrait);
|
||||
|
||||
case Settings::LayoutOption::SingleScreen:
|
||||
#ifndef ANDROID
|
||||
case Settings::LayoutOption::SeparateWindows:
|
||||
#endif
|
||||
{
|
||||
layout =
|
||||
CustomFrameLayout(std::max(Settings::values.custom_top_x.GetValue() +
|
||||
Settings::values.custom_top_width.GetValue(),
|
||||
Settings::values.custom_bottom_x.GetValue() +
|
||||
Settings::values.custom_bottom_width.GetValue()),
|
||||
std::max(Settings::values.custom_top_y.GetValue() +
|
||||
Settings::values.custom_top_height.GetValue(),
|
||||
Settings::values.custom_bottom_y.GetValue() +
|
||||
Settings::values.custom_bottom_height.GetValue()),
|
||||
Settings::values.swap_screen.GetValue(), is_portrait);
|
||||
break;
|
||||
case Settings::LayoutOption::SingleScreen: {
|
||||
const bool swap_screens = is_secondary || Settings::values.swap_screen.GetValue();
|
||||
if (swap_screens) {
|
||||
width = Core::kScreenBottomWidth * res_scale;
|
||||
@ -471,8 +474,10 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
|
||||
if (Settings::values.upright_screen.GetValue()) {
|
||||
std::swap(width, height);
|
||||
}
|
||||
return SingleFrameLayout(width, height, swap_screens,
|
||||
Settings::values.upright_screen.GetValue());
|
||||
|
||||
layout = SingleFrameLayout(width, height, swap_screens,
|
||||
Settings::values.upright_screen.GetValue());
|
||||
break;
|
||||
}
|
||||
|
||||
case Settings::LayoutOption::LargeScreen: {
|
||||
@ -501,10 +506,11 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
|
||||
if (Settings::values.upright_screen.GetValue()) {
|
||||
std::swap(width, height);
|
||||
}
|
||||
return LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||
Settings::values.upright_screen.GetValue(),
|
||||
Settings::values.large_screen_proportion.GetValue(),
|
||||
Settings::values.small_screen_position.GetValue());
|
||||
layout = LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||
Settings::values.upright_screen.GetValue(),
|
||||
Settings::values.large_screen_proportion.GetValue(),
|
||||
Settings::values.small_screen_position.GetValue());
|
||||
break;
|
||||
}
|
||||
case Settings::LayoutOption::SideScreen:
|
||||
width = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale + gap;
|
||||
@ -513,10 +519,10 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
|
||||
if (Settings::values.upright_screen.GetValue()) {
|
||||
std::swap(width, height);
|
||||
}
|
||||
return LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||
Settings::values.upright_screen.GetValue(), 1,
|
||||
Settings::SmallScreenPosition::MiddleRight);
|
||||
|
||||
layout = LargeFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||
Settings::values.upright_screen.GetValue(), 1,
|
||||
Settings::SmallScreenPosition::MiddleRight);
|
||||
break;
|
||||
case Settings::LayoutOption::HybridScreen:
|
||||
height = Core::kScreenTopHeight * res_scale;
|
||||
|
||||
@ -532,9 +538,9 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
|
||||
std::swap(width, height);
|
||||
}
|
||||
|
||||
return HybridScreenLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||
Settings::values.upright_screen.GetValue());
|
||||
|
||||
layout = HybridScreenLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||
Settings::values.upright_screen.GetValue());
|
||||
break;
|
||||
case Settings::LayoutOption::Default:
|
||||
default:
|
||||
width = Core::kScreenTopWidth * res_scale;
|
||||
@ -543,10 +549,13 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
|
||||
if (Settings::values.upright_screen.GetValue()) {
|
||||
std::swap(width, height);
|
||||
}
|
||||
return DefaultFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||
Settings::values.upright_screen.GetValue());
|
||||
layout = DefaultFrameLayout(width, height, Settings::values.swap_screen.GetValue(),
|
||||
Settings::values.upright_screen.GetValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return layout;
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
@ -48,6 +48,8 @@ struct FramebufferLayout {
|
||||
u32 GetScalingRatio() const;
|
||||
|
||||
static float GetAspectRatioValue(Settings::AspectRatio aspect_ratio);
|
||||
|
||||
Settings::StereoRenderOption render_3d_mode = Settings::values.render_3d.GetValue();
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -326,7 +326,7 @@ void RendererOpenGL::InitOpenGLObjects() {
|
||||
glSamplerParameteri(samplers[i].handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
ReloadShader();
|
||||
ReloadShader(Settings::values.render_3d.GetValue());
|
||||
|
||||
// Generate VBO handle for drawing
|
||||
vertex_buffer.Create();
|
||||
@ -372,10 +372,10 @@ void RendererOpenGL::InitOpenGLObjects() {
|
||||
state.Apply();
|
||||
}
|
||||
|
||||
void RendererOpenGL::ReloadShader() {
|
||||
void RendererOpenGL::ReloadShader(Settings::StereoRenderOption render_3d) {
|
||||
// Link shaders and get variable locations
|
||||
std::string shader_data = fragment_shader_precision_OES;
|
||||
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph) {
|
||||
if (render_3d == Settings::StereoRenderOption::Anaglyph) {
|
||||
if (Settings::values.anaglyph_shader_name.GetValue() == "Dubois (builtin)") {
|
||||
shader_data += HostShaders::OPENGL_PRESENT_ANAGLYPH_FRAG;
|
||||
} else {
|
||||
@ -388,9 +388,8 @@ void RendererOpenGL::ReloadShader() {
|
||||
shader_data += shader_text;
|
||||
}
|
||||
}
|
||||
} else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced ||
|
||||
Settings::values.render_3d.GetValue() ==
|
||||
Settings::StereoRenderOption::ReverseInterlaced) {
|
||||
} else if (render_3d == Settings::StereoRenderOption::Interlaced ||
|
||||
render_3d == Settings::StereoRenderOption::ReverseInterlaced) {
|
||||
shader_data += HostShaders::OPENGL_PRESENT_INTERLACED_FRAG;
|
||||
} else {
|
||||
if (Settings::values.pp_shader_name.GetValue() == "None (builtin)") {
|
||||
@ -411,17 +410,16 @@ void RendererOpenGL::ReloadShader() {
|
||||
state.Apply();
|
||||
uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix");
|
||||
uniform_color_texture = glGetUniformLocation(shader.handle, "color_texture");
|
||||
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph ||
|
||||
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced ||
|
||||
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced) {
|
||||
if (render_3d == Settings::StereoRenderOption::Anaglyph ||
|
||||
render_3d == Settings::StereoRenderOption::Interlaced ||
|
||||
render_3d == Settings::StereoRenderOption::ReverseInterlaced) {
|
||||
uniform_color_texture_r = glGetUniformLocation(shader.handle, "color_texture_r");
|
||||
}
|
||||
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced ||
|
||||
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced) {
|
||||
if (render_3d == Settings::StereoRenderOption::Interlaced ||
|
||||
render_3d == Settings::StereoRenderOption::ReverseInterlaced) {
|
||||
GLuint uniform_reverse_interlaced =
|
||||
glGetUniformLocation(shader.handle, "reverse_interlaced");
|
||||
if (Settings::values.render_3d.GetValue() ==
|
||||
Settings::StereoRenderOption::ReverseInterlaced)
|
||||
if (render_3d == Settings::StereoRenderOption::ReverseInterlaced)
|
||||
glUniform1i(uniform_reverse_interlaced, 1);
|
||||
else
|
||||
glUniform1i(uniform_reverse_interlaced, 0);
|
||||
@ -658,7 +656,7 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
||||
// Update fragment shader before drawing
|
||||
shader.Release();
|
||||
// Link shaders and get variable locations
|
||||
ReloadShader();
|
||||
ReloadShader(layout.render_3d_mode);
|
||||
}
|
||||
|
||||
const auto& top_screen = layout.top_screen;
|
||||
@ -676,9 +674,9 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
|
||||
const bool stereo_single_screen =
|
||||
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph ||
|
||||
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced ||
|
||||
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced;
|
||||
layout.render_3d_mode == Settings::StereoRenderOption::Anaglyph ||
|
||||
layout.render_3d_mode == Settings::StereoRenderOption::Interlaced ||
|
||||
layout.render_3d_mode == Settings::StereoRenderOption::ReverseInterlaced;
|
||||
|
||||
// Bind a second texture for the right eye if in Anaglyph mode
|
||||
if (stereo_single_screen) {
|
||||
@ -730,6 +728,9 @@ void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
||||
if (!layout.top_screen_enabled) {
|
||||
return;
|
||||
}
|
||||
int leftside, rightside;
|
||||
leftside = Settings::values.swap_eyes_3d.GetValue() ? 1 : 0;
|
||||
rightside = Settings::values.swap_eyes_3d.GetValue() ? 0 : 1;
|
||||
|
||||
const float top_screen_left = static_cast<float>(top_screen.left);
|
||||
const float top_screen_top = static_cast<float>(top_screen.top);
|
||||
@ -738,7 +739,7 @@ void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
||||
|
||||
const auto orientation = layout.is_rotated ? Layout::DisplayOrientation::Landscape
|
||||
: Layout::DisplayOrientation::Portrait;
|
||||
switch (Settings::values.render_3d.GetValue()) {
|
||||
switch (layout.render_3d_mode) {
|
||||
case Settings::StereoRenderOption::Off: {
|
||||
const int eye = static_cast<int>(Settings::values.mono_render_option.GetValue());
|
||||
DrawSingleScreen(screen_infos[eye], top_screen_left, top_screen_top, top_screen_width,
|
||||
@ -746,29 +747,29 @@ void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::SideBySide: {
|
||||
DrawSingleScreen(screen_infos[0], top_screen_left / 2, top_screen_top, top_screen_width / 2,
|
||||
top_screen_height, orientation);
|
||||
DrawSingleScreen(screen_infos[leftside], top_screen_left / 2, top_screen_top,
|
||||
top_screen_width / 2, top_screen_height, orientation);
|
||||
glUniform1i(uniform_layer, 1);
|
||||
DrawSingleScreen(screen_infos[1],
|
||||
DrawSingleScreen(screen_infos[rightside],
|
||||
static_cast<float>((top_screen_left / 2) + (layout.width / 2)),
|
||||
top_screen_top, top_screen_width / 2, top_screen_height, orientation);
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::ReverseSideBySide: {
|
||||
DrawSingleScreen(screen_infos[1], top_screen_left / 2, top_screen_top, top_screen_width / 2,
|
||||
case Settings::StereoRenderOption::SideBySideFull: {
|
||||
DrawSingleScreen(screen_infos[leftside], top_screen_left, top_screen_top, top_screen_width,
|
||||
top_screen_height, orientation);
|
||||
glUniform1i(uniform_layer, 1);
|
||||
DrawSingleScreen(screen_infos[0],
|
||||
static_cast<float>((top_screen_left / 2) + (layout.width / 2)),
|
||||
top_screen_top, top_screen_width / 2, top_screen_height, orientation);
|
||||
DrawSingleScreen(screen_infos[rightside],
|
||||
static_cast<float>(top_screen_left + layout.width / 2), top_screen_top,
|
||||
top_screen_width, top_screen_height, orientation);
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::CardboardVR: {
|
||||
DrawSingleScreen(screen_infos[0], top_screen_left, top_screen_top, top_screen_width,
|
||||
DrawSingleScreen(screen_infos[leftside], top_screen_left, top_screen_top, top_screen_width,
|
||||
top_screen_height, orientation);
|
||||
glUniform1i(uniform_layer, 1);
|
||||
DrawSingleScreen(
|
||||
screen_infos[1],
|
||||
screen_infos[rightside],
|
||||
static_cast<float>(layout.cardboard.top_screen_right_eye + (layout.width / 2)),
|
||||
top_screen_top, top_screen_width, top_screen_height, orientation);
|
||||
break;
|
||||
@ -776,8 +777,8 @@ void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
||||
case Settings::StereoRenderOption::Anaglyph:
|
||||
case Settings::StereoRenderOption::Interlaced:
|
||||
case Settings::StereoRenderOption::ReverseInterlaced: {
|
||||
DrawSingleScreenStereo(screen_infos[0], screen_infos[1], top_screen_left, top_screen_top,
|
||||
top_screen_width, top_screen_height, orientation);
|
||||
DrawSingleScreenStereo(screen_infos[leftside], screen_infos[rightside], top_screen_left,
|
||||
top_screen_top, top_screen_width, top_screen_height, orientation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -797,31 +798,30 @@ void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout,
|
||||
const auto orientation = layout.is_rotated ? Layout::DisplayOrientation::Landscape
|
||||
: Layout::DisplayOrientation::Portrait;
|
||||
|
||||
bool separate_win = false;
|
||||
#ifndef ANDROID
|
||||
separate_win =
|
||||
(Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows);
|
||||
#endif
|
||||
|
||||
switch (Settings::values.render_3d.GetValue()) {
|
||||
switch (layout.render_3d_mode) {
|
||||
case Settings::StereoRenderOption::Off: {
|
||||
DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top,
|
||||
bottom_screen_width, bottom_screen_height, orientation);
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::SideBySide: // Bottom screen is identical on both sides
|
||||
case Settings::StereoRenderOption::ReverseSideBySide: {
|
||||
if (separate_win) {
|
||||
DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top,
|
||||
bottom_screen_width, bottom_screen_height, orientation);
|
||||
} else {
|
||||
DrawSingleScreen(screen_infos[2], bottom_screen_left / 2, bottom_screen_top,
|
||||
bottom_screen_width / 2, bottom_screen_height, orientation);
|
||||
glUniform1i(uniform_layer, 1);
|
||||
DrawSingleScreen(
|
||||
screen_infos[2], static_cast<float>((bottom_screen_left / 2) + (layout.width / 2)),
|
||||
bottom_screen_top, bottom_screen_width / 2, bottom_screen_height, orientation);
|
||||
}
|
||||
{
|
||||
|
||||
DrawSingleScreen(screen_infos[2], bottom_screen_left / 2, bottom_screen_top,
|
||||
bottom_screen_width / 2, bottom_screen_height, orientation);
|
||||
glUniform1i(uniform_layer, 1);
|
||||
DrawSingleScreen(
|
||||
screen_infos[2], static_cast<float>((bottom_screen_left / 2) + (layout.width / 2)),
|
||||
bottom_screen_top, bottom_screen_width / 2, bottom_screen_height, orientation);
|
||||
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::SideBySideFull: {
|
||||
DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top,
|
||||
bottom_screen_width, bottom_screen_height, orientation);
|
||||
glUniform1i(uniform_layer, 1);
|
||||
DrawSingleScreen(screen_infos[2], bottom_screen_left + layout.width / 2, bottom_screen_top,
|
||||
bottom_screen_width, bottom_screen_height, orientation);
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::CardboardVR: {
|
||||
|
||||
@ -56,7 +56,7 @@ public:
|
||||
|
||||
private:
|
||||
void InitOpenGLObjects();
|
||||
void ReloadShader();
|
||||
void ReloadShader(Settings::StereoRenderOption render_3d);
|
||||
void PrepareRendertarget();
|
||||
void RenderScreenshot();
|
||||
void RenderToMailbox(const Layout::FramebufferLayout& layout,
|
||||
|
||||
@ -575,8 +575,7 @@ void RendererVulkan::FillScreen(Common::Vec3<u8> color, const TextureInfo& textu
|
||||
});
|
||||
}
|
||||
|
||||
void RendererVulkan::ReloadPipeline() {
|
||||
const Settings::StereoRenderOption render_3d = Settings::values.render_3d.GetValue();
|
||||
void RendererVulkan::ReloadPipeline(Settings::StereoRenderOption render_3d) {
|
||||
switch (render_3d) {
|
||||
case Settings::StereoRenderOption::Anaglyph:
|
||||
current_pipeline = 1;
|
||||
@ -748,7 +747,9 @@ void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
||||
if (!layout.top_screen_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
int leftside, rightside;
|
||||
leftside = Settings::values.swap_eyes_3d.GetValue() ? 1 : 0;
|
||||
rightside = Settings::values.swap_eyes_3d.GetValue() ? 0 : 1;
|
||||
const float top_screen_left = static_cast<float>(top_screen.left);
|
||||
const float top_screen_top = static_cast<float>(top_screen.top);
|
||||
const float top_screen_width = static_cast<float>(top_screen.GetWidth());
|
||||
@ -756,7 +757,7 @@ void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
||||
|
||||
const auto orientation = layout.is_rotated ? Layout::DisplayOrientation::Landscape
|
||||
: Layout::DisplayOrientation::Portrait;
|
||||
switch (Settings::values.render_3d.GetValue()) {
|
||||
switch (layout.render_3d_mode) {
|
||||
case Settings::StereoRenderOption::Off: {
|
||||
const int eye = static_cast<int>(Settings::values.mono_render_option.GetValue());
|
||||
DrawSingleScreen(eye, top_screen_left, top_screen_top, top_screen_width, top_screen_height,
|
||||
@ -764,35 +765,36 @@ void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::SideBySide: {
|
||||
DrawSingleScreen(0, top_screen_left / 2, top_screen_top, top_screen_width / 2,
|
||||
DrawSingleScreen(leftside, top_screen_left / 2, top_screen_top, top_screen_width / 2,
|
||||
top_screen_height, orientation);
|
||||
draw_info.layer = 1;
|
||||
DrawSingleScreen(1, static_cast<float>((top_screen_left / 2) + (layout.width / 2)),
|
||||
DrawSingleScreen(rightside, static_cast<float>((top_screen_left / 2) + (layout.width / 2)),
|
||||
top_screen_top, top_screen_width / 2, top_screen_height, orientation);
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::ReverseSideBySide: {
|
||||
DrawSingleScreen(1, top_screen_left / 2, top_screen_top, top_screen_width / 2,
|
||||
case Settings::StereoRenderOption::SideBySideFull: {
|
||||
DrawSingleScreen(leftside, top_screen_left, top_screen_top, top_screen_width,
|
||||
top_screen_height, orientation);
|
||||
draw_info.layer = 1;
|
||||
DrawSingleScreen(0, static_cast<float>((top_screen_left / 2) + (layout.width / 2)),
|
||||
top_screen_top, top_screen_width / 2, top_screen_height, orientation);
|
||||
DrawSingleScreen(rightside, top_screen_left + layout.width / 2, top_screen_top,
|
||||
top_screen_width, top_screen_height, orientation);
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::CardboardVR: {
|
||||
DrawSingleScreen(0, top_screen_left, top_screen_top, top_screen_width, top_screen_height,
|
||||
orientation);
|
||||
DrawSingleScreen(leftside, top_screen_left, top_screen_top, top_screen_width,
|
||||
top_screen_height, orientation);
|
||||
draw_info.layer = 1;
|
||||
DrawSingleScreen(
|
||||
1, static_cast<float>(layout.cardboard.top_screen_right_eye + (layout.width / 2)),
|
||||
rightside,
|
||||
static_cast<float>(layout.cardboard.top_screen_right_eye + (layout.width / 2)),
|
||||
top_screen_top, top_screen_width, top_screen_height, orientation);
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::Anaglyph:
|
||||
case Settings::StereoRenderOption::Interlaced:
|
||||
case Settings::StereoRenderOption::ReverseInterlaced: {
|
||||
DrawSingleScreenStereo(0, 1, top_screen_left, top_screen_top, top_screen_width,
|
||||
top_screen_height, orientation);
|
||||
DrawSingleScreenStereo(leftside, rightside, top_screen_left, top_screen_top,
|
||||
top_screen_width, top_screen_height, orientation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -812,31 +814,29 @@ void RendererVulkan::DrawBottomScreen(const Layout::FramebufferLayout& layout,
|
||||
const auto orientation = layout.is_rotated ? Layout::DisplayOrientation::Landscape
|
||||
: Layout::DisplayOrientation::Portrait;
|
||||
|
||||
bool separate_win = false;
|
||||
#ifndef ANDROID
|
||||
separate_win =
|
||||
(Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows);
|
||||
#endif
|
||||
|
||||
switch (Settings::values.render_3d.GetValue()) {
|
||||
switch (layout.render_3d_mode) {
|
||||
case Settings::StereoRenderOption::Off: {
|
||||
DrawSingleScreen(2, bottom_screen_left, bottom_screen_top, bottom_screen_width,
|
||||
bottom_screen_height, orientation);
|
||||
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::SideBySide: // Bottom screen is identical on both sides
|
||||
case Settings::StereoRenderOption::ReverseSideBySide: {
|
||||
if (separate_win) {
|
||||
DrawSingleScreen(2, bottom_screen_left, bottom_screen_top, bottom_screen_width,
|
||||
bottom_screen_height, orientation);
|
||||
} else {
|
||||
DrawSingleScreen(2, bottom_screen_left / 2, bottom_screen_top, bottom_screen_width / 2,
|
||||
bottom_screen_height, orientation);
|
||||
draw_info.layer = 1;
|
||||
DrawSingleScreen(2, static_cast<float>((bottom_screen_left / 2) + (layout.width / 2)),
|
||||
bottom_screen_top, bottom_screen_width / 2, bottom_screen_height,
|
||||
orientation);
|
||||
}
|
||||
{
|
||||
DrawSingleScreen(2, bottom_screen_left / 2, bottom_screen_top, bottom_screen_width / 2,
|
||||
bottom_screen_height, orientation);
|
||||
draw_info.layer = 1;
|
||||
DrawSingleScreen(2, static_cast<float>((bottom_screen_left / 2) + (layout.width / 2)),
|
||||
bottom_screen_top, bottom_screen_width / 2, bottom_screen_height,
|
||||
orientation);
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::SideBySideFull: {
|
||||
DrawSingleScreen(2, bottom_screen_left, bottom_screen_top, bottom_screen_width,
|
||||
bottom_screen_height, orientation);
|
||||
draw_info.layer = 1;
|
||||
DrawSingleScreen(2, bottom_screen_left + layout.width / 2, bottom_screen_top,
|
||||
bottom_screen_width, bottom_screen_height, orientation);
|
||||
break;
|
||||
}
|
||||
case Settings::StereoRenderOption::CardboardVR: {
|
||||
@ -851,13 +851,8 @@ void RendererVulkan::DrawBottomScreen(const Layout::FramebufferLayout& layout,
|
||||
case Settings::StereoRenderOption::Anaglyph:
|
||||
case Settings::StereoRenderOption::Interlaced:
|
||||
case Settings::StereoRenderOption::ReverseInterlaced: {
|
||||
if (separate_win) {
|
||||
DrawSingleScreen(2, bottom_screen_left, bottom_screen_top, bottom_screen_width,
|
||||
bottom_screen_height, orientation);
|
||||
} else {
|
||||
DrawSingleScreenStereo(2, 2, bottom_screen_left, bottom_screen_top, bottom_screen_width,
|
||||
bottom_screen_height, orientation);
|
||||
}
|
||||
DrawSingleScreenStereo(2, 2, bottom_screen_left, bottom_screen_top, bottom_screen_width,
|
||||
bottom_screen_height, orientation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -871,7 +866,7 @@ void RendererVulkan::DrawScreens(Frame* frame, const Layout::FramebufferLayout&
|
||||
clear_color.float32[2] = Settings::values.bg_blue.GetValue();
|
||||
}
|
||||
if (settings.shader_update_requested.exchange(false)) {
|
||||
ReloadPipeline();
|
||||
ReloadPipeline(layout.render_3d_mode);
|
||||
}
|
||||
|
||||
PrepareDraw(frame, layout);
|
||||
|
||||
@ -80,7 +80,7 @@ public:
|
||||
void TryPresent(int timeout_ms, bool is_secondary) override {}
|
||||
|
||||
private:
|
||||
void ReloadPipeline();
|
||||
void ReloadPipeline(Settings::StereoRenderOption render_3d);
|
||||
void CompileShaders();
|
||||
void BuildLayouts();
|
||||
void BuildPipelines();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user