Better Support for Picture-in-Picture Custom Layouts (Based on #6127) (#6247)

This commit is contained in:
SomeDudeOnDiscord 2023-02-14 16:06:11 -05:00 committed by GitHub
parent ab8d1c7d8b
commit a8e4e11cd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 180 additions and 132 deletions

View file

@ -177,6 +177,8 @@ void Config::ReadValues() {
static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_bottom_right", 360)); static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_bottom_right", 360));
Settings::values.custom_bottom_bottom = Settings::values.custom_bottom_bottom =
static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_bottom_bottom", 480)); static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_bottom_bottom", 480));
Settings::values.custom_second_layer_opacity =
static_cast<u16>(sdl2_config->GetInteger("Layout", "custom_second_layer_opacity", 100));
// Utility // Utility
Settings::values.dump_textures = sdl2_config->GetBoolean("Utility", "dump_textures", false); Settings::values.dump_textures = sdl2_config->GetBoolean("Utility", "dump_textures", false);

View file

@ -204,6 +204,9 @@ custom_bottom_top =
custom_bottom_right = custom_bottom_right =
custom_bottom_bottom = 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. # 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. # 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 # 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent

View file

@ -9,6 +9,7 @@
#include <QSettings> #include <QSettings>
#include "citra_qt/configuration/config.h" #include "citra_qt/configuration/config.h"
#include "common/file_util.h" #include "common/file_util.h"
#include "common/settings.h"
#include "core/frontend/mic.h" #include "core/frontend/mic.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
#include "input_common/main.h" #include "input_common/main.h"
@ -496,6 +497,7 @@ void Config::ReadLayoutValues() {
ReadBasicSetting(Settings::values.custom_bottom_top); ReadBasicSetting(Settings::values.custom_bottom_top);
ReadBasicSetting(Settings::values.custom_bottom_right); ReadBasicSetting(Settings::values.custom_bottom_right);
ReadBasicSetting(Settings::values.custom_bottom_bottom); ReadBasicSetting(Settings::values.custom_bottom_bottom);
ReadBasicSetting(Settings::values.custom_second_layer_opacity);
} }
qt_config->endGroup(); qt_config->endGroup();
@ -1006,6 +1008,7 @@ void Config::SaveLayoutValues() {
WriteBasicSetting(Settings::values.custom_bottom_top); WriteBasicSetting(Settings::values.custom_bottom_top);
WriteBasicSetting(Settings::values.custom_bottom_right); WriteBasicSetting(Settings::values.custom_bottom_right);
WriteBasicSetting(Settings::values.custom_bottom_bottom); WriteBasicSetting(Settings::values.custom_bottom_bottom);
WriteBasicSetting(Settings::values.custom_second_layer_opacity);
} }
qt_config->endGroup(); qt_config->endGroup();

View file

@ -464,6 +464,7 @@ struct Values {
Setting<u16> custom_bottom_top{240, "custom_bottom_top"}; Setting<u16> custom_bottom_top{240, "custom_bottom_top"};
Setting<u16> custom_bottom_right{360, "custom_bottom_right"}; Setting<u16> custom_bottom_right{360, "custom_bottom_right"};
Setting<u16> custom_bottom_bottom{480, "custom_bottom_bottom"}; Setting<u16> custom_bottom_bottom{480, "custom_bottom_bottom"};
Setting<u16> custom_second_layer_opacity{100, "custom_second_layer_opacity"};
SwitchableSetting<double> bg_red{0.f, "bg_red"}; SwitchableSetting<double> bg_red{0.f, "bg_red"};
SwitchableSetting<double> bg_green{0.f, "bg_green"}; SwitchableSetting<double> bg_green{0.f, "bg_green"};

View file

@ -178,7 +178,7 @@ void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height,
layout_option.GetValue(), Settings::values.upright_screen.GetValue()); layout_option.GetValue(), Settings::values.upright_screen.GetValue());
if (Settings::values.custom_layout.GetValue() == true) { if (Settings::values.custom_layout.GetValue() == true) {
layout = Layout::CustomFrameLayout(width, height); layout = Layout::CustomFrameLayout(width, height, Settings::values.swap_screen.GetValue());
} else { } else {
width = std::max(width, min_size.first); width = std::max(width, min_size.first);
height = std::max(height, min_size.second); height = std::max(height, min_size.second);

View file

@ -349,7 +349,7 @@ FramebufferLayout SeparateWindowsLayout(u32 width, u32 height, bool is_secondary
return SingleFrameLayout(width, height, is_secondary, upright); 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(width > 0);
ASSERT(height > 0); ASSERT(height > 0);
@ -364,8 +364,13 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height) {
Settings::values.custom_bottom_right.GetValue(), Settings::values.custom_bottom_right.GetValue(),
Settings::values.custom_bottom_bottom.GetValue()}; Settings::values.custom_bottom_bottom.GetValue()};
res.top_screen = top_screen; if (is_swapped) {
res.bottom_screen = bot_screen; res.top_screen = bot_screen;
res.bottom_screen = top_screen;
} else {
res.top_screen = top_screen;
res.bottom_screen = bot_screen;
}
return res; return res;
} }
@ -375,7 +380,8 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
layout = CustomFrameLayout(std::max(Settings::values.custom_top_right.GetValue(), layout = CustomFrameLayout(std::max(Settings::values.custom_top_right.GetValue(),
Settings::values.custom_bottom_right.GetValue()), Settings::values.custom_bottom_right.GetValue()),
std::max(Settings::values.custom_top_bottom.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 { } else {
int width, height; int width, height;
switch (Settings::values.layout_option.GetValue()) { switch (Settings::values.layout_option.GetValue()) {

View file

@ -114,7 +114,7 @@ FramebufferLayout SeparateWindowsLayout(u32 width, u32 height, bool is_secondary
* @param height Window framebuffer height in pixels * @param height Window framebuffer height in pixels
* @return Newly created FramebufferLayout object with default screen regions initialized * @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 * Convenience method to get frame layout by resolution scale

View file

@ -1002,134 +1002,161 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
} }
glUniform1i(uniform_layer, 0); glUniform1i(uniform_layer, 0);
if (layout.top_screen_enabled) { if (!Settings::values.swap_screen) {
if (layout.is_rotated) { DrawTopScreen(layout, top_screen, stereo_single_screen);
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { glUniform1i(uniform_layer, 0);
int eye = static_cast<int>(Settings::values.mono_render_option.GetValue()); ApplySecondLayerOpacity();
DrawSingleScreenRotated(screen_infos[eye], (float)top_screen.left, DrawBottomScreen(layout, bottom_screen, stereo_single_screen);
(float)top_screen.top, (float)top_screen.GetWidth(), } else {
(float)top_screen.GetHeight()); DrawBottomScreen(layout, bottom_screen, stereo_single_screen);
} else if (Settings::values.render_3d.GetValue() == glUniform1i(uniform_layer, 0);
Settings::StereoRenderOption::SideBySide) { ApplySecondLayerOpacity();
DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2, DrawTopScreen(layout, top_screen, stereo_single_screen);
(float)top_screen.top, (float)top_screen.GetWidth() / 2, }
(float)top_screen.GetHeight()); state.blend.enabled = false;
glUniform1i(uniform_layer, 1); }
DrawSingleScreenRotated(screen_infos[1],
((float)top_screen.left / 2) + ((float)layout.width / 2), void RendererOpenGL::ApplySecondLayerOpacity() {
(float)top_screen.top, (float)top_screen.GetWidth() / 2, if (Settings::values.custom_layout &&
(float)top_screen.GetHeight()); Settings::values.custom_second_layer_opacity.GetValue() < 100) {
} else if (Settings::values.render_3d.GetValue() == state.blend.enabled = true;
Settings::StereoRenderOption::CardboardVR) { state.blend.src_rgb_func = GL_CONSTANT_ALPHA;
DrawSingleScreenRotated(screen_infos[0], layout.top_screen.left, state.blend.src_a_func = GL_CONSTANT_ALPHA;
layout.top_screen.top, layout.top_screen.GetWidth(), state.blend.dst_a_func = GL_ONE_MINUS_CONSTANT_ALPHA;
layout.top_screen.GetHeight()); state.blend.dst_rgb_func = GL_ONE_MINUS_CONSTANT_ALPHA;
glUniform1i(uniform_layer, 1); state.blend.color.alpha = Settings::values.custom_second_layer_opacity.GetValue() / 100.0f;
DrawSingleScreenRotated(screen_infos[1], }
layout.cardboard.top_screen_right_eye + }
((float)layout.width / 2),
layout.top_screen.top, layout.top_screen.GetWidth(), void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout,
layout.top_screen.GetHeight()); const Common::Rectangle<u32>& top_screen,
} else if (stereo_single_screen) { const bool stereo_single_screen) {
DrawSingleScreenStereoRotated( if (!layout.top_screen_enabled) {
screen_infos[0], screen_infos[1], (float)top_screen.left, (float)top_screen.top, return;
(float)top_screen.GetWidth(), (float)top_screen.GetHeight()); }
}
} else { if (layout.is_rotated) {
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) {
int eye = static_cast<int>(Settings::values.mono_render_option.GetValue()); DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left, (float)top_screen.top,
DrawSingleScreen(screen_infos[eye], (float)top_screen.left, (float)top_screen.top, (float)top_screen.GetWidth(), (float)top_screen.GetHeight());
(float)top_screen.GetWidth(), (float)top_screen.GetHeight()); } else if (Settings::values.render_3d.GetValue() ==
} else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::SideBySide) {
Settings::StereoRenderOption::SideBySide) { DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2,
DrawSingleScreen(screen_infos[0], (float)top_screen.left / 2, (float)top_screen.top, (float)top_screen.top, (float)top_screen.GetWidth() / 2,
(float)top_screen.GetWidth() / 2, (float)top_screen.GetHeight()); (float)top_screen.GetHeight());
glUniform1i(uniform_layer, 1); glUniform1i(uniform_layer, 1);
DrawSingleScreen(screen_infos[1], DrawSingleScreenRotated(screen_infos[1],
((float)top_screen.left / 2) + ((float)layout.width / 2), ((float)top_screen.left / 2) + ((float)layout.width / 2),
(float)top_screen.top, (float)top_screen.GetWidth() / 2, (float)top_screen.top, (float)top_screen.GetWidth() / 2,
(float)top_screen.GetHeight()); (float)top_screen.GetHeight());
} else if (Settings::values.render_3d.GetValue() == } else if (Settings::values.render_3d.GetValue() ==
Settings::StereoRenderOption::CardboardVR) { Settings::StereoRenderOption::CardboardVR) {
DrawSingleScreen(screen_infos[0], layout.top_screen.left, layout.top_screen.top, DrawSingleScreenRotated(screen_infos[0], layout.top_screen.left, layout.top_screen.top,
layout.top_screen.GetWidth(), layout.top_screen.GetHeight()); layout.top_screen.GetWidth(), layout.top_screen.GetHeight());
glUniform1i(uniform_layer, 1); glUniform1i(uniform_layer, 1);
DrawSingleScreen(screen_infos[1], DrawSingleScreenRotated(
layout.cardboard.top_screen_right_eye + ((float)layout.width / 2), screen_infos[1], layout.cardboard.top_screen_right_eye + ((float)layout.width / 2),
layout.top_screen.top, layout.top_screen.GetWidth(), layout.top_screen.top, layout.top_screen.GetWidth(), layout.top_screen.GetHeight());
layout.top_screen.GetHeight()); } else if (stereo_single_screen) {
} else if (stereo_single_screen) { DrawSingleScreenStereoRotated(screen_infos[0], screen_infos[1], (float)top_screen.left,
DrawSingleScreenStereo(screen_infos[0], screen_infos[1], (float)top_screen.left, (float)top_screen.top, (float)top_screen.GetWidth(),
(float)top_screen.top, (float)top_screen.GetWidth(), (float)top_screen.GetHeight());
(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) { void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout,
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { const Common::Rectangle<u32>& bottom_screen,
DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left, const bool stereo_single_screen) {
(float)bottom_screen.top, (float)bottom_screen.GetWidth(), if (!layout.bottom_screen_enabled) {
(float)bottom_screen.GetHeight()); return;
} else if (Settings::values.render_3d.GetValue() == }
Settings::StereoRenderOption::SideBySide) {
DrawSingleScreenRotated( if (layout.is_rotated) {
screen_infos[2], (float)bottom_screen.left / 2, (float)bottom_screen.top, if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) {
(float)bottom_screen.GetWidth() / 2, (float)bottom_screen.GetHeight()); DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left,
glUniform1i(uniform_layer, 1); (float)bottom_screen.top, (float)bottom_screen.GetWidth(),
DrawSingleScreenRotated( (float)bottom_screen.GetHeight());
screen_infos[2], ((float)bottom_screen.left / 2) + ((float)layout.width / 2), } else if (Settings::values.render_3d.GetValue() ==
(float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, Settings::StereoRenderOption::SideBySide) {
(float)bottom_screen.GetHeight()); DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left / 2,
} else if (Settings::values.render_3d.GetValue() == (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
Settings::StereoRenderOption::CardboardVR) { (float)bottom_screen.GetHeight());
DrawSingleScreenRotated(screen_infos[2], layout.bottom_screen.left, glUniform1i(uniform_layer, 1);
layout.bottom_screen.top, layout.bottom_screen.GetWidth(), DrawSingleScreenRotated(screen_infos[2],
layout.bottom_screen.GetHeight()); ((float)bottom_screen.left / 2) + ((float)layout.width / 2),
glUniform1i(uniform_layer, 1); (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.GetHeight());
layout.cardboard.bottom_screen_right_eye + } else if (Settings::values.render_3d.GetValue() ==
((float)layout.width / 2), Settings::StereoRenderOption::CardboardVR) {
layout.bottom_screen.top, layout.bottom_screen.GetWidth(), DrawSingleScreenRotated(screen_infos[2], layout.bottom_screen.left,
layout.bottom_screen.GetHeight()); layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
} else if (stereo_single_screen) { layout.bottom_screen.GetHeight());
DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2], glUniform1i(uniform_layer, 1);
(float)bottom_screen.left, (float)bottom_screen.top, DrawSingleScreenRotated(screen_infos[2],
(float)bottom_screen.GetWidth(), layout.cardboard.bottom_screen_right_eye +
(float)bottom_screen.GetHeight()); ((float)layout.width / 2),
} layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
} else { layout.bottom_screen.GetHeight());
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) { } else if (stereo_single_screen) {
DrawSingleScreen(screen_infos[2], (float)bottom_screen.left, DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2],
(float)bottom_screen.top, (float)bottom_screen.GetWidth(), (float)bottom_screen.left, (float)bottom_screen.top,
(float)bottom_screen.GetHeight()); (float)bottom_screen.GetWidth(),
} else if (Settings::values.render_3d.GetValue() == (float)bottom_screen.GetHeight());
Settings::StereoRenderOption::SideBySide) { }
DrawSingleScreen(screen_infos[2], (float)bottom_screen.left / 2, } else {
(float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) {
(float)bottom_screen.GetHeight()); DrawSingleScreen(screen_infos[2], (float)bottom_screen.left, (float)bottom_screen.top,
glUniform1i(uniform_layer, 1); (float)bottom_screen.GetWidth(), (float)bottom_screen.GetHeight());
DrawSingleScreen(screen_infos[2], } else if (Settings::values.render_3d.GetValue() ==
((float)bottom_screen.left / 2) + ((float)layout.width / 2), Settings::StereoRenderOption::SideBySide) {
(float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, DrawSingleScreen(screen_infos[2], (float)bottom_screen.left / 2,
(float)bottom_screen.GetHeight()); (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
} else if (Settings::values.render_3d.GetValue() == (float)bottom_screen.GetHeight());
Settings::StereoRenderOption::CardboardVR) { glUniform1i(uniform_layer, 1);
DrawSingleScreen(screen_infos[2], layout.bottom_screen.left, DrawSingleScreen(screen_infos[2],
layout.bottom_screen.top, layout.bottom_screen.GetWidth(), ((float)bottom_screen.left / 2) + ((float)layout.width / 2),
layout.bottom_screen.GetHeight()); (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
glUniform1i(uniform_layer, 1); (float)bottom_screen.GetHeight());
DrawSingleScreen(screen_infos[2], } else if (Settings::values.render_3d.GetValue() ==
layout.cardboard.bottom_screen_right_eye + Settings::StereoRenderOption::CardboardVR) {
((float)layout.width / 2), DrawSingleScreen(screen_infos[2], layout.bottom_screen.left, layout.bottom_screen.top,
layout.bottom_screen.top, layout.bottom_screen.GetWidth(), layout.bottom_screen.GetWidth(), layout.bottom_screen.GetHeight());
layout.bottom_screen.GetHeight()); glUniform1i(uniform_layer, 1);
} else if (stereo_single_screen) { DrawSingleScreen(screen_infos[2],
DrawSingleScreenStereo(screen_infos[2], screen_infos[2], (float)bottom_screen.left, layout.cardboard.bottom_screen_right_eye + ((float)layout.width / 2),
(float)bottom_screen.top, (float)bottom_screen.GetWidth(), layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
(float)bottom_screen.GetHeight()); 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());
} }
} }
} }

View file

@ -89,6 +89,12 @@ private:
void ConfigureFramebufferTexture(TextureInfo& texture, void ConfigureFramebufferTexture(TextureInfo& texture,
const GPU::Regs::FramebufferConfig& framebuffer); const GPU::Regs::FramebufferConfig& framebuffer);
void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped); void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped);
void ApplySecondLayerOpacity();
void DrawBottomScreen(const Layout::FramebufferLayout& layout,
const Common::Rectangle<u32>& bottom_screen,
const bool stereo_single_screen);
void DrawTopScreen(const Layout::FramebufferLayout& layout,
const Common::Rectangle<u32>& top_screen, const bool stereo_single_screen);
void DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y, float w, float h); 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 DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h);
void DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l, void DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l,