From 05e00d3a47e05121a55c3b55bfacff70e6346d6a Mon Sep 17 00:00:00 2001 From: David Griswold Date: Tue, 27 Aug 2024 11:27:22 -0300 Subject: [PATCH] add swap_eyes_3d setting and enable side by side full --- src/common/settings.h | 11 +-- src/core/frontend/emu_window.cpp | 46 +++++++---- src/core/frontend/framebuffer_layout.cpp | 82 +++++++++++-------- .../renderer_opengl/renderer_opengl.cpp | 38 ++++++--- .../renderer_vulkan/renderer_vulkan.cpp | 38 +++++---- 5 files changed, 136 insertions(+), 79 deletions(-) diff --git a/src/common/settings.h b/src/common/settings.h index f8e9e3e2e..c5e943b94 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -70,11 +70,11 @@ enum class SmallScreenPosition : u32 { enum class StereoRenderOption : u32 { Off = 0, SideBySide = 1, - ReverseSideBySide = 2, - Anaglyph = 3, - Interlaced = 4, - ReverseInterlaced = 5, - CardboardVR = 6 + SideBySideFull = 2, + Anaglyph = 4, + Interlaced = 5, + ReverseInterlaced = 6, + CardboardVR = 7 }; // Which eye to render when 3d is off. 800px wide mode could be added here in the future, when @@ -541,6 +541,7 @@ struct Values { SwitchableSetting render_3d{StereoRenderOption::Off, "render_3d"}; SwitchableSetting factor_3d{0, "factor_3d"}; + SwitchableSetting swap_eyes_3d{false, "swap_eyes"}; SwitchableSetting mono_render_option{MonoRenderOption::LeftEye, "mono_render_option"}; diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index 6c2811cf0..1d058d6af 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -67,9 +67,11 @@ bool EmuWindow::IsWithinTouchscreen(const Layout::FramebufferLayout& layout, uns #endif Settings::StereoRenderOption render_3d_mode = Settings::values.render_3d.GetValue(); - - if (render_3d_mode == Settings::StereoRenderOption::SideBySide || - render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) { + if (framebuffer_x > layout.width && + render_3d_mode == Settings::StereoRenderOption::SideBySideFull) { + framebuffer_x = static_cast(framebuffer_x - layout.width); + } + 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 && @@ -94,17 +96,17 @@ bool EmuWindow::IsWithinTouchscreen(const Layout::FramebufferLayout& layout, uns std::tuple EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const { Settings::StereoRenderOption render_3d_mode = Settings::values.render_3d.GetValue(); - - if (new_x >= framebuffer_layout.width / 2) { - if (render_3d_mode == Settings::StereoRenderOption::SideBySide || - render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) + if (new_x >= framebuffer_layout.width && + render_3d_mode == Settings::StereoRenderOption::SideBySideFull) { + new_x -= framebuffer_layout.width; + } else if (new_x >= framebuffer_layout.width / 2) { + if (render_3d_mode == Settings::StereoRenderOption::SideBySide) 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) { + 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 { @@ -133,18 +135,18 @@ bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) return false; - - if (framebuffer_x >= framebuffer_layout.width / 2) { - if (render_3d_mode == Settings::StereoRenderOption::SideBySide || - render_3d_mode == Settings::StereoRenderOption::ReverseSideBySide) + if (framebuffer_x >= framebuffer_layout.width && + render_3d_mode == Settings::StereoRenderOption::SideBySideFull) { + framebuffer_x -= framebuffer_layout.width; + } else if (framebuffer_x >= framebuffer_layout.width / 2) { + if (render_3d_mode == Settings::StereoRenderOption::SideBySide) 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) { + if (render_3d_mode == Settings::StereoRenderOption::SideBySide) { touch_state->touch_x = static_cast(framebuffer_x - framebuffer_layout.bottom_screen.left / 2) / (framebuffer_layout.bottom_screen.right / 2 - @@ -197,6 +199,13 @@ 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 (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySideFull) { + if (Settings::values.upright_screen.GetValue()) { + height = height / 2; + } else { + width = width / 2; + } + } if (is_portrait_mode) { switch (portrait_layout_option) { case Settings::PortraitLayoutOption::PortraitTopFullWidth: @@ -251,6 +260,13 @@ void EmuWindow::UpdateCurrentFramebufferLayout(u32 width, u32 height, bool is_po break; } } + if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySideFull) { + if (Settings::values.upright_screen.GetValue()) { + layout.height = height * 2; + } else { + layout.width = width * 2; + } + } UpdateMinimumWindowSize(min_size); if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::CardboardVR) { diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index 7cf52a29c..00353dc4f 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp @@ -347,39 +347,47 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height, bool is_swapped, bool FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondary, bool is_portrait) { int width, height; + bool stereo_full = + Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySideFull; + 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; height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; - return PortraitTopFullFrameLayout(width, height, - Settings::values.swap_screen.GetValue()); + layout = + PortraitTopFullFrameLayout(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); + 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: #ifndef ANDROID @@ -394,11 +402,17 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar width = Core::kScreenTopWidth * res_scale; height = Core::kScreenTopHeight * res_scale; } + if (Settings::values.render_3d.GetValue() == + Settings::StereoRenderOption::SideBySideFull) { + width = width / 2; + } 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: { @@ -427,10 +441,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(), - 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()); } case Settings::LayoutOption::SideScreen: width = (Core::kScreenTopWidth + Core::kScreenBottomWidth) * res_scale; @@ -439,9 +453,9 @@ 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); case Settings::LayoutOption::Default: default: @@ -451,10 +465,14 @@ 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; } } + if (stereo_full) + layout.width *= 2; + return layout; UNREACHABLE(); } diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 4f5dcb131..abc1cca10 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -726,6 +726,9 @@ void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout, if (!layout.top_screen_enabled) { return; } + int leftside, rightside; + leftside = Settings::values.swap_eyes_3d.GetValue() ? 0 : 1; + rightside = Settings::values.swap_eyes_3d.GetValue() ? 1 : 0; const float top_screen_left = static_cast(top_screen.left); const float top_screen_top = static_cast(top_screen.top); @@ -742,29 +745,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((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((top_screen_left / 2) + (layout.width / 2)), - top_screen_top, top_screen_width / 2, top_screen_height, orientation); + // DrawSingleScreen(screen_infos[rightside], + // static_cast(top_screen_left + layout.width), + // 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(layout.cardboard.top_screen_right_eye + (layout.width / 2)), top_screen_top, top_screen_width, top_screen_height, orientation); break; @@ -772,8 +775,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; } } @@ -800,7 +803,7 @@ void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout, break; } case Settings::StereoRenderOption::SideBySide: // Bottom screen is identical on both sides - case Settings::StereoRenderOption::ReverseSideBySide: { + { DrawSingleScreen(screen_infos[2], bottom_screen_left / 2, bottom_screen_top, bottom_screen_width / 2, bottom_screen_height, orientation); glUniform1i(uniform_layer, 1); @@ -809,6 +812,15 @@ void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout, 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], static_cast(bottom_screen_left + layout.width), + // bottom_screen_top, bottom_screen_width, bottom_screen_height, orientation); + break; + } case Settings::StereoRenderOption::CardboardVR: { DrawSingleScreen(screen_infos[2], bottom_screen_left, bottom_screen_top, bottom_screen_width, bottom_screen_height, orientation); diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 6c95a22b7..7f6309866 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -675,7 +675,9 @@ void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout, if (!layout.top_screen_enabled) { return; } - + int leftside, rightside; + leftside = Settings::values.swap_eyes_3d.GetValue() ? 0 : 1; + rightside = Settings::values.swap_eyes_3d.GetValue() ? 1 : 0; const float top_screen_left = static_cast(top_screen.left); const float top_screen_top = static_cast(top_screen.top); const float top_screen_width = static_cast(top_screen.GetWidth()); @@ -691,35 +693,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((top_screen_left / 2) + (layout.width / 2)), + DrawSingleScreen(rightside, static_cast((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((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(layout.cardboard.top_screen_right_eye + (layout.width / 2)), + rightside, + static_cast(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; } } @@ -745,8 +748,7 @@ void RendererVulkan::DrawBottomScreen(const Layout::FramebufferLayout& layout, bottom_screen_height, orientation); break; } - case Settings::StereoRenderOption::SideBySide: // Bottom screen is identical on both sides - case Settings::StereoRenderOption::ReverseSideBySide: { + case Settings::StereoRenderOption::SideBySide: { DrawSingleScreen(2, bottom_screen_left / 2, bottom_screen_top, bottom_screen_width / 2, bottom_screen_height, orientation); draw_info.layer = 1; @@ -755,6 +757,14 @@ void RendererVulkan::DrawBottomScreen(const Layout::FramebufferLayout& layout, 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: { DrawSingleScreen(2, bottom_screen_left, bottom_screen_top, bottom_screen_width, bottom_screen_height, orientation);