From a8e4e11cd5bbe35a12bfef7af0396c4193d784df Mon Sep 17 00:00:00 2001 From: SomeDudeOnDiscord <122324510+SomeDudeOnDiscord@users.noreply.github.com> Date: Tue, 14 Feb 2023 16:06:11 -0500 Subject: [PATCH] Better Support for Picture-in-Picture Custom Layouts (Based on #6127) (#6247) --- src/citra/config.cpp | 2 + src/citra/default_ini.h | 3 + src/citra_qt/configuration/config.cpp | 3 + src/common/settings.h | 1 + src/core/frontend/emu_window.cpp | 2 +- src/core/frontend/framebuffer_layout.cpp | 14 +- src/core/frontend/framebuffer_layout.h | 2 +- .../renderer_opengl/renderer_opengl.cpp | 279 ++++++++++-------- .../renderer_opengl/renderer_opengl.h | 6 + 9 files changed, 180 insertions(+), 132 deletions(-) diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 64d33a930..cf8a1e01e 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -177,6 +177,8 @@ void Config::ReadValues() { static_cast(sdl2_config->GetInteger("Layout", "custom_bottom_right", 360)); Settings::values.custom_bottom_bottom = static_cast(sdl2_config->GetInteger("Layout", "custom_bottom_bottom", 480)); + Settings::values.custom_second_layer_opacity = + static_cast(sdl2_config->GetInteger("Layout", "custom_second_layer_opacity", 100)); // Utility Settings::values.dump_textures = sdl2_config->GetBoolean("Utility", "dump_textures", false); diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index e84532a3c..9cc72ba09 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -204,6 +204,9 @@ custom_bottom_top = custom_bottom_right = custom_bottom_bottom = +# Opacity of second layer when using custom layout option (bottom screen unless swapped) +custom_second_layer_opacity = + # Swaps the prominent screen with the other screen. # For example, if Single Screen is chosen, setting this to 1 will display the bottom screen instead of the top screen. # 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp index 5e5d41e83..bfccdbe18 100644 --- a/src/citra_qt/configuration/config.cpp +++ b/src/citra_qt/configuration/config.cpp @@ -9,6 +9,7 @@ #include #include "citra_qt/configuration/config.h" #include "common/file_util.h" +#include "common/settings.h" #include "core/frontend/mic.h" #include "core/hle/service/service.h" #include "input_common/main.h" @@ -496,6 +497,7 @@ void Config::ReadLayoutValues() { ReadBasicSetting(Settings::values.custom_bottom_top); ReadBasicSetting(Settings::values.custom_bottom_right); ReadBasicSetting(Settings::values.custom_bottom_bottom); + ReadBasicSetting(Settings::values.custom_second_layer_opacity); } qt_config->endGroup(); @@ -1006,6 +1008,7 @@ void Config::SaveLayoutValues() { WriteBasicSetting(Settings::values.custom_bottom_top); WriteBasicSetting(Settings::values.custom_bottom_right); WriteBasicSetting(Settings::values.custom_bottom_bottom); + WriteBasicSetting(Settings::values.custom_second_layer_opacity); } qt_config->endGroup(); diff --git a/src/common/settings.h b/src/common/settings.h index 7fec09ba0..a29123af1 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -464,6 +464,7 @@ struct Values { Setting custom_bottom_top{240, "custom_bottom_top"}; Setting custom_bottom_right{360, "custom_bottom_right"}; Setting custom_bottom_bottom{480, "custom_bottom_bottom"}; + Setting custom_second_layer_opacity{100, "custom_second_layer_opacity"}; SwitchableSetting bg_red{0.f, "bg_red"}; SwitchableSetting bg_green{0.f, "bg_green"}; diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index 2222ece02..acb81fdaa 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -178,7 +178,7 @@ void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height, layout_option.GetValue(), Settings::values.upright_screen.GetValue()); if (Settings::values.custom_layout.GetValue() == true) { - layout = Layout::CustomFrameLayout(width, height); + layout = Layout::CustomFrameLayout(width, height, Settings::values.swap_screen.GetValue()); } else { width = std::max(width, min_size.first); height = std::max(height, min_size.second); diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index 4b3512d6a..75f330f18 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp @@ -349,7 +349,7 @@ FramebufferLayout SeparateWindowsLayout(u32 width, u32 height, bool is_secondary return SingleFrameLayout(width, height, is_secondary, upright); } -FramebufferLayout CustomFrameLayout(u32 width, u32 height) { +FramebufferLayout CustomFrameLayout(u32 width, u32 height, bool is_swapped) { ASSERT(width > 0); ASSERT(height > 0); @@ -364,8 +364,13 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height) { Settings::values.custom_bottom_right.GetValue(), Settings::values.custom_bottom_bottom.GetValue()}; - res.top_screen = top_screen; - res.bottom_screen = bot_screen; + if (is_swapped) { + res.top_screen = bot_screen; + res.bottom_screen = top_screen; + } else { + res.top_screen = top_screen; + res.bottom_screen = bot_screen; + } return res; } @@ -375,7 +380,8 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar layout = CustomFrameLayout(std::max(Settings::values.custom_top_right.GetValue(), Settings::values.custom_bottom_right.GetValue()), std::max(Settings::values.custom_top_bottom.GetValue(), - Settings::values.custom_bottom_bottom.GetValue())); + Settings::values.custom_bottom_bottom.GetValue()), + Settings::values.swap_screen.GetValue()); } else { int width, height; switch (Settings::values.layout_option.GetValue()) { diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h index 92b43f285..763262663 100644 --- a/src/core/frontend/framebuffer_layout.h +++ b/src/core/frontend/framebuffer_layout.h @@ -114,7 +114,7 @@ FramebufferLayout SeparateWindowsLayout(u32 width, u32 height, bool is_secondary * @param height Window framebuffer height in pixels * @return Newly created FramebufferLayout object with default screen regions initialized */ -FramebufferLayout CustomFrameLayout(u32 width, u32 height); +FramebufferLayout CustomFrameLayout(u32 width, u32 height, bool is_swapped); /** * Convenience method to get frame layout by resolution scale diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 5b8b7f060..89e58a9dc 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -1002,134 +1002,161 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f } glUniform1i(uniform_layer, 0); - if (layout.top_screen_enabled) { - if (layout.is_rotated) { - if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { - int eye = static_cast(Settings::values.mono_render_option.GetValue()); - DrawSingleScreenRotated(screen_infos[eye], (float)top_screen.left, - (float)top_screen.top, (float)top_screen.GetWidth(), - (float)top_screen.GetHeight()); - } else if (Settings::values.render_3d.GetValue() == - Settings::StereoRenderOption::SideBySide) { - DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2, - (float)top_screen.top, (float)top_screen.GetWidth() / 2, - (float)top_screen.GetHeight()); - glUniform1i(uniform_layer, 1); - DrawSingleScreenRotated(screen_infos[1], - ((float)top_screen.left / 2) + ((float)layout.width / 2), - (float)top_screen.top, (float)top_screen.GetWidth() / 2, - (float)top_screen.GetHeight()); - } else if (Settings::values.render_3d.GetValue() == - Settings::StereoRenderOption::CardboardVR) { - DrawSingleScreenRotated(screen_infos[0], layout.top_screen.left, - layout.top_screen.top, layout.top_screen.GetWidth(), - layout.top_screen.GetHeight()); - glUniform1i(uniform_layer, 1); - DrawSingleScreenRotated(screen_infos[1], - layout.cardboard.top_screen_right_eye + - ((float)layout.width / 2), - layout.top_screen.top, layout.top_screen.GetWidth(), - layout.top_screen.GetHeight()); - } else if (stereo_single_screen) { - DrawSingleScreenStereoRotated( - screen_infos[0], screen_infos[1], (float)top_screen.left, (float)top_screen.top, - (float)top_screen.GetWidth(), (float)top_screen.GetHeight()); - } - } else { - if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { - int eye = static_cast(Settings::values.mono_render_option.GetValue()); - DrawSingleScreen(screen_infos[eye], (float)top_screen.left, (float)top_screen.top, - (float)top_screen.GetWidth(), (float)top_screen.GetHeight()); - } else if (Settings::values.render_3d.GetValue() == - Settings::StereoRenderOption::SideBySide) { - DrawSingleScreen(screen_infos[0], (float)top_screen.left / 2, (float)top_screen.top, - (float)top_screen.GetWidth() / 2, (float)top_screen.GetHeight()); - glUniform1i(uniform_layer, 1); - DrawSingleScreen(screen_infos[1], - ((float)top_screen.left / 2) + ((float)layout.width / 2), - (float)top_screen.top, (float)top_screen.GetWidth() / 2, - (float)top_screen.GetHeight()); - } else if (Settings::values.render_3d.GetValue() == - Settings::StereoRenderOption::CardboardVR) { - DrawSingleScreen(screen_infos[0], layout.top_screen.left, layout.top_screen.top, - layout.top_screen.GetWidth(), layout.top_screen.GetHeight()); - glUniform1i(uniform_layer, 1); - DrawSingleScreen(screen_infos[1], - layout.cardboard.top_screen_right_eye + ((float)layout.width / 2), - layout.top_screen.top, layout.top_screen.GetWidth(), - layout.top_screen.GetHeight()); - } else if (stereo_single_screen) { - DrawSingleScreenStereo(screen_infos[0], screen_infos[1], (float)top_screen.left, - (float)top_screen.top, (float)top_screen.GetWidth(), - (float)top_screen.GetHeight()); - } + if (!Settings::values.swap_screen) { + DrawTopScreen(layout, top_screen, stereo_single_screen); + glUniform1i(uniform_layer, 0); + ApplySecondLayerOpacity(); + DrawBottomScreen(layout, bottom_screen, stereo_single_screen); + } else { + DrawBottomScreen(layout, bottom_screen, stereo_single_screen); + glUniform1i(uniform_layer, 0); + ApplySecondLayerOpacity(); + DrawTopScreen(layout, top_screen, stereo_single_screen); + } + state.blend.enabled = false; +} + +void RendererOpenGL::ApplySecondLayerOpacity() { + if (Settings::values.custom_layout && + Settings::values.custom_second_layer_opacity.GetValue() < 100) { + state.blend.enabled = true; + state.blend.src_rgb_func = GL_CONSTANT_ALPHA; + state.blend.src_a_func = GL_CONSTANT_ALPHA; + state.blend.dst_a_func = GL_ONE_MINUS_CONSTANT_ALPHA; + state.blend.dst_rgb_func = GL_ONE_MINUS_CONSTANT_ALPHA; + state.blend.color.alpha = Settings::values.custom_second_layer_opacity.GetValue() / 100.0f; + } +} + +void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout, + const Common::Rectangle& top_screen, + const bool stereo_single_screen) { + if (!layout.top_screen_enabled) { + return; + } + + if (layout.is_rotated) { + if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { + DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left, (float)top_screen.top, + (float)top_screen.GetWidth(), (float)top_screen.GetHeight()); + } else if (Settings::values.render_3d.GetValue() == + Settings::StereoRenderOption::SideBySide) { + DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2, + (float)top_screen.top, (float)top_screen.GetWidth() / 2, + (float)top_screen.GetHeight()); + glUniform1i(uniform_layer, 1); + DrawSingleScreenRotated(screen_infos[1], + ((float)top_screen.left / 2) + ((float)layout.width / 2), + (float)top_screen.top, (float)top_screen.GetWidth() / 2, + (float)top_screen.GetHeight()); + } else if (Settings::values.render_3d.GetValue() == + Settings::StereoRenderOption::CardboardVR) { + DrawSingleScreenRotated(screen_infos[0], layout.top_screen.left, layout.top_screen.top, + layout.top_screen.GetWidth(), layout.top_screen.GetHeight()); + glUniform1i(uniform_layer, 1); + DrawSingleScreenRotated( + screen_infos[1], layout.cardboard.top_screen_right_eye + ((float)layout.width / 2), + layout.top_screen.top, layout.top_screen.GetWidth(), layout.top_screen.GetHeight()); + } else if (stereo_single_screen) { + DrawSingleScreenStereoRotated(screen_infos[0], screen_infos[1], (float)top_screen.left, + (float)top_screen.top, (float)top_screen.GetWidth(), + (float)top_screen.GetHeight()); + } + } else { + if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { + DrawSingleScreen(screen_infos[0], (float)top_screen.left, (float)top_screen.top, + (float)top_screen.GetWidth(), (float)top_screen.GetHeight()); + } else if (Settings::values.render_3d.GetValue() == + Settings::StereoRenderOption::SideBySide) { + DrawSingleScreen(screen_infos[0], (float)top_screen.left / 2, (float)top_screen.top, + (float)top_screen.GetWidth() / 2, (float)top_screen.GetHeight()); + glUniform1i(uniform_layer, 1); + DrawSingleScreen(screen_infos[1], + ((float)top_screen.left / 2) + ((float)layout.width / 2), + (float)top_screen.top, (float)top_screen.GetWidth() / 2, + (float)top_screen.GetHeight()); + } else if (Settings::values.render_3d.GetValue() == + Settings::StereoRenderOption::CardboardVR) { + DrawSingleScreen(screen_infos[0], layout.top_screen.left, layout.top_screen.top, + layout.top_screen.GetWidth(), layout.top_screen.GetHeight()); + glUniform1i(uniform_layer, 1); + DrawSingleScreen( + screen_infos[1], layout.cardboard.top_screen_right_eye + ((float)layout.width / 2), + layout.top_screen.top, layout.top_screen.GetWidth(), layout.top_screen.GetHeight()); + } else if (stereo_single_screen) { + DrawSingleScreenStereo(screen_infos[0], screen_infos[1], (float)top_screen.left, + (float)top_screen.top, (float)top_screen.GetWidth(), + (float)top_screen.GetHeight()); } } - glUniform1i(uniform_layer, 0); - if (layout.bottom_screen_enabled) { - if (layout.is_rotated) { - if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { - DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left, - (float)bottom_screen.top, (float)bottom_screen.GetWidth(), - (float)bottom_screen.GetHeight()); - } else if (Settings::values.render_3d.GetValue() == - Settings::StereoRenderOption::SideBySide) { - DrawSingleScreenRotated( - screen_infos[2], (float)bottom_screen.left / 2, (float)bottom_screen.top, - (float)bottom_screen.GetWidth() / 2, (float)bottom_screen.GetHeight()); - glUniform1i(uniform_layer, 1); - DrawSingleScreenRotated( - screen_infos[2], ((float)bottom_screen.left / 2) + ((float)layout.width / 2), - (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, - (float)bottom_screen.GetHeight()); - } else if (Settings::values.render_3d.GetValue() == - Settings::StereoRenderOption::CardboardVR) { - DrawSingleScreenRotated(screen_infos[2], layout.bottom_screen.left, - layout.bottom_screen.top, layout.bottom_screen.GetWidth(), - layout.bottom_screen.GetHeight()); - glUniform1i(uniform_layer, 1); - DrawSingleScreenRotated(screen_infos[2], - layout.cardboard.bottom_screen_right_eye + - ((float)layout.width / 2), - layout.bottom_screen.top, layout.bottom_screen.GetWidth(), - layout.bottom_screen.GetHeight()); - } else if (stereo_single_screen) { - DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2], - (float)bottom_screen.left, (float)bottom_screen.top, - (float)bottom_screen.GetWidth(), - (float)bottom_screen.GetHeight()); - } - } else { - if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { - DrawSingleScreen(screen_infos[2], (float)bottom_screen.left, - (float)bottom_screen.top, (float)bottom_screen.GetWidth(), - (float)bottom_screen.GetHeight()); - } else if (Settings::values.render_3d.GetValue() == - Settings::StereoRenderOption::SideBySide) { - DrawSingleScreen(screen_infos[2], (float)bottom_screen.left / 2, - (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, - (float)bottom_screen.GetHeight()); - glUniform1i(uniform_layer, 1); - DrawSingleScreen(screen_infos[2], - ((float)bottom_screen.left / 2) + ((float)layout.width / 2), - (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, - (float)bottom_screen.GetHeight()); - } else if (Settings::values.render_3d.GetValue() == - Settings::StereoRenderOption::CardboardVR) { - DrawSingleScreen(screen_infos[2], layout.bottom_screen.left, - layout.bottom_screen.top, layout.bottom_screen.GetWidth(), - layout.bottom_screen.GetHeight()); - glUniform1i(uniform_layer, 1); - DrawSingleScreen(screen_infos[2], - layout.cardboard.bottom_screen_right_eye + - ((float)layout.width / 2), - layout.bottom_screen.top, layout.bottom_screen.GetWidth(), - layout.bottom_screen.GetHeight()); - } else if (stereo_single_screen) { - DrawSingleScreenStereo(screen_infos[2], screen_infos[2], (float)bottom_screen.left, - (float)bottom_screen.top, (float)bottom_screen.GetWidth(), - (float)bottom_screen.GetHeight()); - } +} + +void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout, + const Common::Rectangle& bottom_screen, + const bool stereo_single_screen) { + if (!layout.bottom_screen_enabled) { + return; + } + + if (layout.is_rotated) { + if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { + DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left, + (float)bottom_screen.top, (float)bottom_screen.GetWidth(), + (float)bottom_screen.GetHeight()); + } else if (Settings::values.render_3d.GetValue() == + Settings::StereoRenderOption::SideBySide) { + DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left / 2, + (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, + (float)bottom_screen.GetHeight()); + glUniform1i(uniform_layer, 1); + DrawSingleScreenRotated(screen_infos[2], + ((float)bottom_screen.left / 2) + ((float)layout.width / 2), + (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, + (float)bottom_screen.GetHeight()); + } else if (Settings::values.render_3d.GetValue() == + Settings::StereoRenderOption::CardboardVR) { + DrawSingleScreenRotated(screen_infos[2], layout.bottom_screen.left, + layout.bottom_screen.top, layout.bottom_screen.GetWidth(), + layout.bottom_screen.GetHeight()); + glUniform1i(uniform_layer, 1); + DrawSingleScreenRotated(screen_infos[2], + layout.cardboard.bottom_screen_right_eye + + ((float)layout.width / 2), + layout.bottom_screen.top, layout.bottom_screen.GetWidth(), + layout.bottom_screen.GetHeight()); + } else if (stereo_single_screen) { + DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2], + (float)bottom_screen.left, (float)bottom_screen.top, + (float)bottom_screen.GetWidth(), + (float)bottom_screen.GetHeight()); + } + } else { + if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { + DrawSingleScreen(screen_infos[2], (float)bottom_screen.left, (float)bottom_screen.top, + (float)bottom_screen.GetWidth(), (float)bottom_screen.GetHeight()); + } else if (Settings::values.render_3d.GetValue() == + Settings::StereoRenderOption::SideBySide) { + DrawSingleScreen(screen_infos[2], (float)bottom_screen.left / 2, + (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, + (float)bottom_screen.GetHeight()); + glUniform1i(uniform_layer, 1); + DrawSingleScreen(screen_infos[2], + ((float)bottom_screen.left / 2) + ((float)layout.width / 2), + (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, + (float)bottom_screen.GetHeight()); + } else if (Settings::values.render_3d.GetValue() == + Settings::StereoRenderOption::CardboardVR) { + DrawSingleScreen(screen_infos[2], layout.bottom_screen.left, layout.bottom_screen.top, + layout.bottom_screen.GetWidth(), layout.bottom_screen.GetHeight()); + glUniform1i(uniform_layer, 1); + DrawSingleScreen(screen_infos[2], + layout.cardboard.bottom_screen_right_eye + ((float)layout.width / 2), + layout.bottom_screen.top, layout.bottom_screen.GetWidth(), + layout.bottom_screen.GetHeight()); + } else if (stereo_single_screen) { + DrawSingleScreenStereo(screen_infos[2], screen_infos[2], (float)bottom_screen.left, + (float)bottom_screen.top, (float)bottom_screen.GetWidth(), + (float)bottom_screen.GetHeight()); } } } diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 0cd2e7089..a168b055e 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -89,6 +89,12 @@ private: void ConfigureFramebufferTexture(TextureInfo& texture, const GPU::Regs::FramebufferConfig& framebuffer); void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped); + void ApplySecondLayerOpacity(); + void DrawBottomScreen(const Layout::FramebufferLayout& layout, + const Common::Rectangle& bottom_screen, + const bool stereo_single_screen); + void DrawTopScreen(const Layout::FramebufferLayout& layout, + const Common::Rectangle& top_screen, const bool stereo_single_screen); void DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y, float w, float h); void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h); void DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l,