mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #5906 from SachinVin/android2
Backport some more stuff from android
This commit is contained in:
		
						commit
						6dfb74a8b9
					
				
					 12 changed files with 331 additions and 19 deletions
				
			
		|  | @ -696,8 +696,8 @@ void SetUserPath(const std::string& path) { | ||||||
|         g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); |         g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); | ||||||
|         g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); |         g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); | ||||||
| #elif ANDROID | #elif ANDROID | ||||||
|         if (FileUtil::Exists(ROOT_DIR DIR_SEP SDCARD_DIR)) { |         if (FileUtil::Exists(DIR_SEP SDCARD_DIR)) { | ||||||
|             user_path = ROOT_DIR DIR_SEP SDCARD_DIR DIR_SEP EMU_DATA_DIR DIR_SEP; |             user_path = DIR_SEP SDCARD_DIR DIR_SEP EMU_DATA_DIR DIR_SEP; | ||||||
|             g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); |             g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); | ||||||
|             g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); |             g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -541,11 +541,11 @@ void System::Shutdown(bool is_deserializing) { | ||||||
|     archive_manager.reset(); |     archive_manager.reset(); | ||||||
|     service_manager.reset(); |     service_manager.reset(); | ||||||
|     dsp_core.reset(); |     dsp_core.reset(); | ||||||
|     cpu_cores.clear(); |  | ||||||
|     kernel.reset(); |     kernel.reset(); | ||||||
|  |     cpu_cores.clear(); | ||||||
|     timing.reset(); |     timing.reset(); | ||||||
| 
 | 
 | ||||||
|     if (video_dumper->IsDumping()) { |     if (video_dumper && video_dumper->IsDumping()) { | ||||||
|         video_dumper->StopDumping(); |         video_dumper->StopDumping(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -554,6 +554,8 @@ void System::Shutdown(bool is_deserializing) { | ||||||
|         room_member->SendGameInfo(game_info); |         room_member->SendGameInfo(game_info); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     memory.reset(); | ||||||
|  | 
 | ||||||
|     LOG_DEBUG(Core, "Shutdown OK"); |     LOG_DEBUG(Core, "Shutdown OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -73,6 +73,14 @@ static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigne | ||||||
|                   framebuffer_x < layout.bottom_screen.right / 2) || |                   framebuffer_x < layout.bottom_screen.right / 2) || | ||||||
|                  (framebuffer_x >= (layout.bottom_screen.left / 2) + (layout.width / 2) && |                  (framebuffer_x >= (layout.bottom_screen.left / 2) + (layout.width / 2) && | ||||||
|                   framebuffer_x < (layout.bottom_screen.right / 2) + (layout.width / 2)))); |                   framebuffer_x < (layout.bottom_screen.right / 2) + (layout.width / 2)))); | ||||||
|  |     } else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||||
|  |         return (framebuffer_y >= layout.bottom_screen.top && | ||||||
|  |                 framebuffer_y < layout.bottom_screen.bottom && | ||||||
|  |                 ((framebuffer_x >= layout.bottom_screen.left && | ||||||
|  |                   framebuffer_x < layout.bottom_screen.right) || | ||||||
|  |                  (framebuffer_x >= layout.cardboard.bottom_screen_right_eye + (layout.width / 2) && | ||||||
|  |                   framebuffer_x < layout.cardboard.bottom_screen_right_eye + | ||||||
|  |                                       layout.bottom_screen.GetWidth() + (layout.width / 2)))); | ||||||
|     } else { |     } else { | ||||||
|         return (framebuffer_y >= layout.bottom_screen.top && |         return (framebuffer_y >= layout.bottom_screen.top && | ||||||
|                 framebuffer_y < layout.bottom_screen.bottom && |                 framebuffer_y < layout.bottom_screen.bottom && | ||||||
|  | @ -82,9 +90,14 @@ static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigne | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const { | std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) const { | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { |     if (new_x >= framebuffer_layout.width / 2) { | ||||||
|         if (new_x >= framebuffer_layout.width / 2) |         if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) | ||||||
|             new_x -= framebuffer_layout.width / 2; |             new_x -= framebuffer_layout.width / 2; | ||||||
|  |         else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) | ||||||
|  |             new_x -= | ||||||
|  |                 (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); | ||||||
|  |     } | ||||||
|  |     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { | ||||||
|         new_x = std::max(new_x, framebuffer_layout.bottom_screen.left / 2); |         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); |         new_x = std::min(new_x, framebuffer_layout.bottom_screen.right / 2 - 1); | ||||||
|     } else { |     } else { | ||||||
|  | @ -98,13 +111,17 @@ std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsi | ||||||
|     return std::make_tuple(new_x, new_y); |     return std::make_tuple(new_x, new_y); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { | bool EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { | ||||||
|     if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) |     if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) | ||||||
|         return; |         return false; | ||||||
| 
 | 
 | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide && |     if (framebuffer_x >= framebuffer_layout.width / 2) { | ||||||
|         framebuffer_x >= framebuffer_layout.width / 2) |         if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) | ||||||
|             framebuffer_x -= framebuffer_layout.width / 2; |             framebuffer_x -= framebuffer_layout.width / 2; | ||||||
|  |         else if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) | ||||||
|  |             framebuffer_x -= | ||||||
|  |                 (framebuffer_layout.width / 2) - (framebuffer_layout.cardboard.user_x_shift * 2); | ||||||
|  |     } | ||||||
|     std::lock_guard guard(touch_state->mutex); |     std::lock_guard guard(touch_state->mutex); | ||||||
|     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { |     if (Settings::values.render_3d == Settings::StereoRenderOption::SideBySide) { | ||||||
|         touch_state->touch_x = |         touch_state->touch_x = | ||||||
|  | @ -126,6 +143,7 @@ void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     touch_state->touch_pressed = true; |     touch_state->touch_pressed = true; | ||||||
|  |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmuWindow::TouchReleased() { | void EmuWindow::TouchReleased() { | ||||||
|  | @ -145,7 +163,8 @@ void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) { | ||||||
|     TouchPressed(framebuffer_x, framebuffer_y); |     TouchPressed(framebuffer_x, framebuffer_y); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) { | void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height, | ||||||
|  |                                                bool is_portrait_mode) { | ||||||
|     Layout::FramebufferLayout layout; |     Layout::FramebufferLayout layout; | ||||||
|     const auto layout_option = Settings::values.layout_option; |     const auto layout_option = Settings::values.layout_option; | ||||||
|     const auto min_size = |     const auto min_size = | ||||||
|  | @ -156,6 +175,12 @@ void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) | ||||||
|     } 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); | ||||||
|  | 
 | ||||||
|  |         // If in portrait mode, only the MobilePortrait option really makes sense
 | ||||||
|  |         const Settings::LayoutOption layout_option = is_portrait_mode | ||||||
|  |                                                          ? Settings::LayoutOption::MobilePortrait | ||||||
|  |                                                          : Settings::values.layout_option; | ||||||
|  | 
 | ||||||
|         switch (layout_option) { |         switch (layout_option) { | ||||||
|         case Settings::LayoutOption::SingleScreen: |         case Settings::LayoutOption::SingleScreen: | ||||||
|             layout = Layout::SingleFrameLayout(width, height, Settings::values.swap_screen, |             layout = Layout::SingleFrameLayout(width, height, Settings::values.swap_screen, | ||||||
|  | @ -169,6 +194,13 @@ void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) | ||||||
|             layout = Layout::SideFrameLayout(width, height, Settings::values.swap_screen, |             layout = Layout::SideFrameLayout(width, height, Settings::values.swap_screen, | ||||||
|                                              Settings::values.upright_screen); |                                              Settings::values.upright_screen); | ||||||
|             break; |             break; | ||||||
|  |         case Settings::LayoutOption::MobilePortrait: | ||||||
|  |             layout = Layout::MobilePortraitFrameLayout(width, height, Settings::values.swap_screen); | ||||||
|  |             break; | ||||||
|  |         case Settings::LayoutOption::MobileLandscape: | ||||||
|  |             layout = Layout::MobileLandscapeFrameLayout(width, height, Settings::values.swap_screen, | ||||||
|  |                                                         2.25f, false); | ||||||
|  |             break; | ||||||
|         case Settings::LayoutOption::Default: |         case Settings::LayoutOption::Default: | ||||||
|         default: |         default: | ||||||
|             layout = Layout::DefaultFrameLayout(width, height, Settings::values.swap_screen, |             layout = Layout::DefaultFrameLayout(width, height, Settings::values.swap_screen, | ||||||
|  | @ -177,6 +209,9 @@ void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) | ||||||
|         } |         } | ||||||
|         UpdateMinimumWindowSize(min_size); |         UpdateMinimumWindowSize(min_size); | ||||||
|     } |     } | ||||||
|  |     if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||||
|  |         layout = Layout::GetCardboardSettings(layout); | ||||||
|  |     } | ||||||
|     NotifyFramebufferLayoutChanged(layout); |     NotifyFramebufferLayoutChanged(layout); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -115,8 +115,9 @@ public: | ||||||
|      * Signal that a touch pressed event has occurred (e.g. mouse click pressed) |      * Signal that a touch pressed event has occurred (e.g. mouse click pressed) | ||||||
|      * @param framebuffer_x Framebuffer x-coordinate that was pressed |      * @param framebuffer_x Framebuffer x-coordinate that was pressed | ||||||
|      * @param framebuffer_y Framebuffer y-coordinate that was pressed |      * @param framebuffer_y Framebuffer y-coordinate that was pressed | ||||||
|  |      * @returns True if the coordinates are within the touchpad, otherwise false | ||||||
|      */ |      */ | ||||||
|     void TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y); |     bool TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y); | ||||||
| 
 | 
 | ||||||
|     /// Signal that a touch released event has occurred (e.g. mouse click released)
 |     /// Signal that a touch released event has occurred (e.g. mouse click released)
 | ||||||
|     void TouchReleased(); |     void TouchReleased(); | ||||||
|  | @ -159,7 +160,8 @@ public: | ||||||
|      * Convenience method to update the current frame layout |      * Convenience method to update the current frame layout | ||||||
|      * Read from the current settings to determine which layout to use. |      * Read from the current settings to determine which layout to use. | ||||||
|      */ |      */ | ||||||
|     void UpdateCurrentFramebufferLayout(unsigned width, unsigned height); |     void UpdateCurrentFramebufferLayout(unsigned width, unsigned height, | ||||||
|  |                                         bool is_portrait_mode = {}); | ||||||
| 
 | 
 | ||||||
|     std::unique_ptr<TextureMailbox> mailbox = nullptr; |     std::unique_ptr<TextureMailbox> mailbox = nullptr; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -117,6 +117,82 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool swapped, bool u | ||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | FramebufferLayout MobilePortraitFrameLayout(u32 width, u32 height, bool swapped) { | ||||||
|  |     ASSERT(width > 0); | ||||||
|  |     ASSERT(height > 0); | ||||||
|  | 
 | ||||||
|  |     FramebufferLayout res{width, height, true, true, {}, {}}; | ||||||
|  |     // Default layout gives equal screen sizes to the top and bottom screen
 | ||||||
|  |     Common::Rectangle<u32> screen_window_area{0, 0, width, height / 2}; | ||||||
|  |     Common::Rectangle<u32> top_screen = maxRectangle(screen_window_area, TOP_SCREEN_ASPECT_RATIO); | ||||||
|  |     Common::Rectangle<u32> bot_screen = maxRectangle(screen_window_area, BOT_SCREEN_ASPECT_RATIO); | ||||||
|  | 
 | ||||||
|  |     float window_aspect_ratio = static_cast<float>(height) / width; | ||||||
|  |     // both screens height are taken into account by multiplying by 2
 | ||||||
|  |     float emulation_aspect_ratio = TOP_SCREEN_ASPECT_RATIO * 2; | ||||||
|  | 
 | ||||||
|  |     if (window_aspect_ratio < emulation_aspect_ratio) { | ||||||
|  |         // Apply borders to the left and right sides of the window.
 | ||||||
|  |         top_screen = | ||||||
|  |             top_screen.TranslateX((screen_window_area.GetWidth() - top_screen.GetWidth()) / 2); | ||||||
|  |         bot_screen = | ||||||
|  |             bot_screen.TranslateX((screen_window_area.GetWidth() - bot_screen.GetWidth()) / 2); | ||||||
|  |     } else { | ||||||
|  |         // Window is narrower than the emulation content
 | ||||||
|  |         // Recalculate the bottom screen to account for the width difference between top and bottom
 | ||||||
|  | 
 | ||||||
|  |         bot_screen = bot_screen.TranslateX((top_screen.GetWidth() - bot_screen.GetWidth()) / 2); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Move the top screen to the bottom if we are swapped.
 | ||||||
|  |     res.top_screen = swapped ? top_screen.TranslateY(bot_screen.GetHeight()) : top_screen; | ||||||
|  |     res.bottom_screen = swapped ? bot_screen : bot_screen.TranslateY(top_screen.GetHeight()); | ||||||
|  | 
 | ||||||
|  |     return res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FramebufferLayout MobileLandscapeFrameLayout(u32 width, u32 height, bool swapped, | ||||||
|  |                                              float scale_factor, bool center_vertical) { | ||||||
|  |     ASSERT(width > 0); | ||||||
|  |     ASSERT(height > 0); | ||||||
|  | 
 | ||||||
|  |     FramebufferLayout res{width, height, true, true, {}, {}}; | ||||||
|  |     // Split the window into two parts. Give 4x width to the main screen and 1x width to the small
 | ||||||
|  |     // To do that, find the total emulation box and maximize that based on window size
 | ||||||
|  |     float window_aspect_ratio = static_cast<float>(height) / width; | ||||||
|  |     float emulation_aspect_ratio = | ||||||
|  |         swapped ? Core::kScreenBottomHeight * scale_factor / | ||||||
|  |                       (Core::kScreenBottomWidth * scale_factor + Core::kScreenTopWidth) | ||||||
|  |                 : Core::kScreenTopHeight * scale_factor / | ||||||
|  |                       (Core::kScreenTopWidth * scale_factor + Core::kScreenBottomWidth); | ||||||
|  |     float large_screen_aspect_ratio = swapped ? BOT_SCREEN_ASPECT_RATIO : TOP_SCREEN_ASPECT_RATIO; | ||||||
|  |     float small_screen_aspect_ratio = swapped ? TOP_SCREEN_ASPECT_RATIO : BOT_SCREEN_ASPECT_RATIO; | ||||||
|  | 
 | ||||||
|  |     Common::Rectangle<u32> screen_window_area{0, 0, width, height}; | ||||||
|  |     Common::Rectangle<u32> total_rect = maxRectangle(screen_window_area, emulation_aspect_ratio); | ||||||
|  |     Common::Rectangle<u32> large_screen = maxRectangle(total_rect, large_screen_aspect_ratio); | ||||||
|  |     Common::Rectangle<u32> fourth_size_rect = total_rect.Scale(1.f / scale_factor); | ||||||
|  |     Common::Rectangle<u32> small_screen = maxRectangle(fourth_size_rect, small_screen_aspect_ratio); | ||||||
|  | 
 | ||||||
|  |     if (window_aspect_ratio < emulation_aspect_ratio) { | ||||||
|  |         large_screen = | ||||||
|  |             large_screen.TranslateX((screen_window_area.GetWidth() - total_rect.GetWidth()) / 2); | ||||||
|  |     } else if (center_vertical) { | ||||||
|  |         large_screen = large_screen.TranslateY((height - total_rect.GetHeight()) / 2); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Shift the small screen to the bottom right corner
 | ||||||
|  |     small_screen = small_screen.TranslateX(large_screen.right); | ||||||
|  |     if (center_vertical) { | ||||||
|  |         small_screen.TranslateY(large_screen.GetHeight() + large_screen.top - | ||||||
|  |                                 small_screen.GetHeight()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     res.top_screen = swapped ? small_screen : large_screen; | ||||||
|  |     res.bottom_screen = swapped ? large_screen : small_screen; | ||||||
|  |     return res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool swapped, bool upright) { | FramebufferLayout SingleFrameLayout(u32 width, u32 height, bool swapped, bool upright) { | ||||||
|     ASSERT(width > 0); |     ASSERT(width > 0); | ||||||
|     ASSERT(height > 0); |     ASSERT(height > 0); | ||||||
|  | @ -346,6 +422,22 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { | ||||||
|             layout = SideFrameLayout(width, height, Settings::values.swap_screen, |             layout = SideFrameLayout(width, height, Settings::values.swap_screen, | ||||||
|                                      Settings::values.upright_screen); |                                      Settings::values.upright_screen); | ||||||
|             break; |             break; | ||||||
|  |         case Settings::LayoutOption::MobilePortrait: | ||||||
|  |             width = Core::kScreenTopWidth * res_scale; | ||||||
|  |             height = (Core::kScreenTopHeight + Core::kScreenBottomHeight) * res_scale; | ||||||
|  |             layout = MobilePortraitFrameLayout(width, height, Settings::values.swap_screen); | ||||||
|  |             break; | ||||||
|  |         case Settings::LayoutOption::MobileLandscape: | ||||||
|  |             if (Settings::values.swap_screen) { | ||||||
|  |                 width = (Core::kScreenBottomWidth + Core::kScreenTopWidth / 2.25f) * res_scale; | ||||||
|  |                 height = Core::kScreenBottomHeight * res_scale; | ||||||
|  |             } else { | ||||||
|  |                 width = (Core::kScreenTopWidth + Core::kScreenBottomWidth / 2.25f) * res_scale; | ||||||
|  |                 height = Core::kScreenTopHeight * res_scale; | ||||||
|  |             } | ||||||
|  |             layout = MobileLandscapeFrameLayout(width, height, Settings::values.swap_screen, 2.25f, | ||||||
|  |                                                 false); | ||||||
|  |             break; | ||||||
|         case Settings::LayoutOption::Default: |         case Settings::LayoutOption::Default: | ||||||
|         default: |         default: | ||||||
|             if (Settings::values.upright_screen) { |             if (Settings::values.upright_screen) { | ||||||
|  | @ -360,9 +452,92 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     if (Settings::values.render_3d == Settings::StereoRenderOption::CardboardVR) { | ||||||
|  |         layout = Layout::GetCardboardSettings(layout); | ||||||
|  |     } | ||||||
|     return layout; |     return layout; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | FramebufferLayout GetCardboardSettings(FramebufferLayout layout) { | ||||||
|  |     FramebufferLayout newLayout = layout; | ||||||
|  |     float top_screen_left = 0; | ||||||
|  |     float top_screen_top = 0; | ||||||
|  |     float bottom_screen_left = 0; | ||||||
|  |     float bottom_screen_top = 0; | ||||||
|  | 
 | ||||||
|  |     float cardboardScreenScale = Settings::values.cardboard_screen_size / 100.0f; | ||||||
|  |     float top_screen_width = layout.top_screen.GetWidth() / 2.0f * cardboardScreenScale; | ||||||
|  |     float top_screen_height = layout.top_screen.GetHeight() / 2.0f * cardboardScreenScale; | ||||||
|  |     float bottom_screen_width = layout.bottom_screen.GetWidth() / 2.0f * cardboardScreenScale; | ||||||
|  |     float bottom_screen_height = layout.bottom_screen.GetHeight() / 2.0f * cardboardScreenScale; | ||||||
|  |     bool is_swapped = Settings::values.swap_screen; | ||||||
|  |     bool is_portrait = layout.height > layout.width; | ||||||
|  | 
 | ||||||
|  |     float cardboardScreenWidth; | ||||||
|  |     float cardboardScreenHeight; | ||||||
|  |     switch (Settings::values.layout_option) { | ||||||
|  |     case Settings::LayoutOption::MobileLandscape: | ||||||
|  |     case Settings::LayoutOption::SideScreen: | ||||||
|  |         // If orientation is portrait, only use MobilePortrait
 | ||||||
|  |         if (!is_portrait) { | ||||||
|  |             cardboardScreenWidth = top_screen_width + bottom_screen_width; | ||||||
|  |             cardboardScreenHeight = is_swapped ? bottom_screen_height : top_screen_height; | ||||||
|  |             if (is_swapped) | ||||||
|  |                 top_screen_left += bottom_screen_width; | ||||||
|  |             else | ||||||
|  |                 bottom_screen_left += top_screen_width; | ||||||
|  |             break; | ||||||
|  |         } else { | ||||||
|  |             [[fallthrough]]; | ||||||
|  |         } | ||||||
|  |     case Settings::LayoutOption::SingleScreen: | ||||||
|  |     default: | ||||||
|  |         if (!is_portrait) { | ||||||
|  |             // Default values when using LayoutOption::SingleScreen
 | ||||||
|  |             cardboardScreenWidth = is_swapped ? bottom_screen_width : top_screen_width; | ||||||
|  |             cardboardScreenHeight = is_swapped ? bottom_screen_height : top_screen_height; | ||||||
|  |             break; | ||||||
|  |         } else { | ||||||
|  |             [[fallthrough]]; | ||||||
|  |         } | ||||||
|  |     case Settings::LayoutOption::MobilePortrait: | ||||||
|  |         cardboardScreenWidth = top_screen_width; | ||||||
|  |         cardboardScreenHeight = top_screen_height + bottom_screen_height; | ||||||
|  |         bottom_screen_left += (top_screen_width - bottom_screen_width) / 2.0f; | ||||||
|  |         if (is_swapped) | ||||||
|  |             top_screen_top += bottom_screen_height; | ||||||
|  |         else | ||||||
|  |             bottom_screen_top += top_screen_height; | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |     float cardboardMaxXShift = (layout.width / 2.0f - cardboardScreenWidth) / 2.0f; | ||||||
|  |     float cardboardUserXShift = (Settings::values.cardboard_x_shift / 100.0f) * cardboardMaxXShift; | ||||||
|  |     float cardboardMaxYShift = ((float)layout.height - cardboardScreenHeight) / 2.0f; | ||||||
|  |     float cardboardUserYShift = (Settings::values.cardboard_y_shift / 100.0f) * cardboardMaxYShift; | ||||||
|  | 
 | ||||||
|  |     // Center the screens and apply user Y shift
 | ||||||
|  |     newLayout.top_screen.left = top_screen_left + cardboardMaxXShift; | ||||||
|  |     newLayout.top_screen.top = top_screen_top + cardboardMaxYShift + cardboardUserYShift; | ||||||
|  |     newLayout.bottom_screen.left = bottom_screen_left + cardboardMaxXShift; | ||||||
|  |     newLayout.bottom_screen.top = bottom_screen_top + cardboardMaxYShift + cardboardUserYShift; | ||||||
|  | 
 | ||||||
|  |     // Set the X coordinates for the right eye and apply user X shift
 | ||||||
|  |     newLayout.cardboard.top_screen_right_eye = newLayout.top_screen.left - cardboardUserXShift; | ||||||
|  |     newLayout.top_screen.left += cardboardUserXShift; | ||||||
|  |     newLayout.cardboard.bottom_screen_right_eye = | ||||||
|  |         newLayout.bottom_screen.left - cardboardUserXShift; | ||||||
|  |     newLayout.bottom_screen.left += cardboardUserXShift; | ||||||
|  |     newLayout.cardboard.user_x_shift = cardboardUserXShift; | ||||||
|  | 
 | ||||||
|  |     // Update right/bottom instead of passing new variables for width/height
 | ||||||
|  |     newLayout.top_screen.right = newLayout.top_screen.left + top_screen_width; | ||||||
|  |     newLayout.top_screen.bottom = newLayout.top_screen.top + top_screen_height; | ||||||
|  |     newLayout.bottom_screen.right = newLayout.bottom_screen.left + bottom_screen_width; | ||||||
|  |     newLayout.bottom_screen.bottom = newLayout.bottom_screen.top + bottom_screen_height; | ||||||
|  | 
 | ||||||
|  |     return newLayout; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout, | std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout, | ||||||
|                                                        bool upright_screen) { |                                                        bool upright_screen) { | ||||||
|     unsigned min_width, min_height; |     unsigned min_width, min_height; | ||||||
|  |  | ||||||
|  | @ -9,6 +9,13 @@ | ||||||
| 
 | 
 | ||||||
| namespace Layout { | namespace Layout { | ||||||
| 
 | 
 | ||||||
|  | /// Describes the horizontal coordinates for the right eye screen when using Cardboard VR
 | ||||||
|  | struct CardboardSettings { | ||||||
|  |     float top_screen_right_eye; | ||||||
|  |     float bottom_screen_right_eye; | ||||||
|  |     float user_x_shift; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /// Describes the layout of the window framebuffer (size and top/bottom screen positions)
 | /// Describes the layout of the window framebuffer (size and top/bottom screen positions)
 | ||||||
| struct FramebufferLayout { | struct FramebufferLayout { | ||||||
|     u32 width; |     u32 width; | ||||||
|  | @ -19,6 +26,8 @@ struct FramebufferLayout { | ||||||
|     Common::Rectangle<u32> bottom_screen; |     Common::Rectangle<u32> bottom_screen; | ||||||
|     bool is_rotated = true; |     bool is_rotated = true; | ||||||
| 
 | 
 | ||||||
|  |     CardboardSettings cardboard; | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Returns the ration of pixel size of the top screen, compared to the native size of the 3DS |      * Returns the ration of pixel size of the top screen, compared to the native size of the 3DS | ||||||
|      * screen. |      * screen. | ||||||
|  | @ -35,6 +44,29 @@ struct FramebufferLayout { | ||||||
|  */ |  */ | ||||||
| FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool is_swapped, bool upright); | FramebufferLayout DefaultFrameLayout(u32 width, u32 height, bool is_swapped, bool upright); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Factory method for constructing a mobile portrait FramebufferLayout | ||||||
|  |  * @param width Window framebuffer width in pixels | ||||||
|  |  * @param height Window framebuffer height in pixels | ||||||
|  |  * @param is_swapped if true, the bottom screen will be displayed above the top screen | ||||||
|  |  * @return Newly created FramebufferLayout object with mobile portrait screen regions initialized | ||||||
|  |  */ | ||||||
|  | FramebufferLayout MobilePortraitFrameLayout(u32 width, u32 height, bool is_swapped); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Factory method for constructing a Frame with the a 4x size Top screen with a 1x size bottom | ||||||
|  |  * screen on the right | ||||||
|  |  * This is useful in particular because it matches well with a 1920x1080 resolution monitor | ||||||
|  |  * @param width Window framebuffer width in pixels | ||||||
|  |  * @param height Window framebuffer height in pixels | ||||||
|  |  * @param is_swapped if true, the bottom screen will be the large display | ||||||
|  |  * @param scale_factor Scale factor to use for bottom screen with respect to top screen | ||||||
|  |  * @param center_vertical When true, centers the top and bottom screens vertically | ||||||
|  |  * @return Newly created FramebufferLayout object with default screen regions initialized | ||||||
|  |  */ | ||||||
|  | FramebufferLayout MobileLandscapeFrameLayout(u32 width, u32 height, bool is_swapped, | ||||||
|  |                                              float scale_factor, bool center_vertical); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Factory method for constructing a FramebufferLayout with only the top or bottom screen |  * Factory method for constructing a FramebufferLayout with only the top or bottom screen | ||||||
|  * @param width Window framebuffer width in pixels |  * @param width Window framebuffer width in pixels | ||||||
|  | @ -81,6 +113,13 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height); | ||||||
|  */ |  */ | ||||||
| FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale); | FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Convenience method for transforming a frame layout when using Cardboard VR | ||||||
|  |  * @param layout frame layout to transform | ||||||
|  |  * @return layout transformed with the user cardboard settings | ||||||
|  |  */ | ||||||
|  | FramebufferLayout GetCardboardSettings(FramebufferLayout layout); | ||||||
|  | 
 | ||||||
| std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout, | std::pair<unsigned, unsigned> GetMinimumSizeFromLayout(Settings::LayoutOption layout, | ||||||
|                                                        bool upright_screen); |                                                        bool upright_screen); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -76,7 +76,7 @@ void UnregisterFactory(const std::string& name) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Create an input device from given paramters. |  * Create an input device from given parameters. | ||||||
|  * @tparam InputDeviceType the type of input devices to create |  * @tparam InputDeviceType the type of input devices to create | ||||||
|  * @param params a serialized ParamPackage string contains all parameters for creating the device |  * @param params a serialized ParamPackage string contains all parameters for creating the device | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | @ -33,9 +33,11 @@ void Apply() { | ||||||
|     VideoCore::g_hw_shader_accurate_mul = values.shaders_accurate_mul; |     VideoCore::g_hw_shader_accurate_mul = values.shaders_accurate_mul; | ||||||
|     VideoCore::g_use_disk_shader_cache = values.use_disk_shader_cache; |     VideoCore::g_use_disk_shader_cache = values.use_disk_shader_cache; | ||||||
| 
 | 
 | ||||||
|  | #ifndef ANDROID | ||||||
|     if (VideoCore::g_renderer) { |     if (VideoCore::g_renderer) { | ||||||
|         VideoCore::g_renderer->UpdateCurrentFramebufferLayout(); |         VideoCore::g_renderer->UpdateCurrentFramebufferLayout(); | ||||||
|     } |     } | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|     VideoCore::g_renderer_bg_color_update_requested = true; |     VideoCore::g_renderer_bg_color_update_requested = true; | ||||||
|     VideoCore::g_renderer_sampler_update_requested = true; |     VideoCore::g_renderer_sampler_update_requested = true; | ||||||
|  |  | ||||||
|  | @ -24,6 +24,14 @@ enum class LayoutOption { | ||||||
|     SingleScreen, |     SingleScreen, | ||||||
|     LargeScreen, |     LargeScreen, | ||||||
|     SideScreen, |     SideScreen, | ||||||
|  | 
 | ||||||
|  |     // Similiar to default, but better for mobile devices in portrait mode. Top screen in clamped to
 | ||||||
|  |     // the top of the frame, and the bottom screen is enlarged to match the top screen.
 | ||||||
|  |     MobilePortrait, | ||||||
|  | 
 | ||||||
|  |     // Similiar to LargeScreen, but better for mobile devices in landscape mode. The screens are
 | ||||||
|  |     // clamped to the top of the frame, and the bottom screen is a bit bigger.
 | ||||||
|  |     MobileLandscape, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum class MicInputType { | enum class MicInputType { | ||||||
|  | @ -32,7 +40,14 @@ enum class MicInputType { | ||||||
|     Static, |     Static, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum class StereoRenderOption { Off, SideBySide, Anaglyph, Interlaced, ReverseInterlaced }; | enum class StereoRenderOption { | ||||||
|  |     Off, | ||||||
|  |     SideBySide, | ||||||
|  |     Anaglyph, | ||||||
|  |     Interlaced, | ||||||
|  |     ReverseInterlaced, | ||||||
|  |     CardboardVR | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| namespace NativeButton { | namespace NativeButton { | ||||||
| enum Values { | enum Values { | ||||||
|  | @ -182,6 +197,10 @@ struct Values { | ||||||
|     StereoRenderOption render_3d; |     StereoRenderOption render_3d; | ||||||
|     std::atomic<u8> factor_3d; |     std::atomic<u8> factor_3d; | ||||||
| 
 | 
 | ||||||
|  |     int cardboard_screen_size; | ||||||
|  |     int cardboard_x_shift; | ||||||
|  |     int cardboard_y_shift; | ||||||
|  | 
 | ||||||
|     bool filter_mode; |     bool filter_mode; | ||||||
|     std::string pp_shader_name; |     std::string pp_shader_name; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,9 +11,9 @@ | ||||||
| 
 | 
 | ||||||
| RendererBase::RendererBase(Frontend::EmuWindow& window) : render_window{window} {} | RendererBase::RendererBase(Frontend::EmuWindow& window) : render_window{window} {} | ||||||
| RendererBase::~RendererBase() = default; | RendererBase::~RendererBase() = default; | ||||||
| void RendererBase::UpdateCurrentFramebufferLayout() { | void RendererBase::UpdateCurrentFramebufferLayout(bool is_portrait_mode) { | ||||||
|     const Layout::FramebufferLayout& layout = render_window.GetFramebufferLayout(); |     const Layout::FramebufferLayout& layout = render_window.GetFramebufferLayout(); | ||||||
|     render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height); |     render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height, is_portrait_mode); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RendererBase::RefreshRasterizerSetting() { | void RendererBase::RefreshRasterizerSetting() { | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ public: | ||||||
|     virtual void CleanupVideoDumping() = 0; |     virtual void CleanupVideoDumping() = 0; | ||||||
| 
 | 
 | ||||||
|     /// Updates the framebuffer layout of the contained render window handle.
 |     /// Updates the framebuffer layout of the contained render window handle.
 | ||||||
|     void UpdateCurrentFramebufferLayout(); |     void UpdateCurrentFramebufferLayout(bool is_portrait_mode = {}); | ||||||
| 
 | 
 | ||||||
|     // Getter/setter functions:
 |     // Getter/setter functions:
 | ||||||
|     // ------------------------
 |     // ------------------------
 | ||||||
|  |  | ||||||
|  | @ -1016,6 +1016,16 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                                         ((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 == 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) { |             } else if (stereo_single_screen) { | ||||||
|                 DrawSingleScreenStereoRotated( |                 DrawSingleScreenStereoRotated( | ||||||
|                     screen_infos[0], screen_infos[1], (float)top_screen.left, (float)top_screen.top, |                     screen_infos[0], screen_infos[1], (float)top_screen.left, (float)top_screen.top, | ||||||
|  | @ -1033,6 +1043,14 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                                  ((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 == 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) { |             } else if (stereo_single_screen) { | ||||||
|                 DrawSingleScreenStereo(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(), | ||||||
|  | @ -1056,6 +1074,16 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                     screen_infos[2], ((float)bottom_screen.left / 2) + ((float)layout.width / 2), |                     screen_infos[2], ((float)bottom_screen.left / 2) + ((float)layout.width / 2), | ||||||
|                     (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, |                     (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, | ||||||
|                     (float)bottom_screen.GetHeight()); |                     (float)bottom_screen.GetHeight()); | ||||||
|  |             } else if (Settings::values.render_3d == 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) { |             } else if (stereo_single_screen) { | ||||||
|                 DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2], |                 DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2], | ||||||
|                                               (float)bottom_screen.left, (float)bottom_screen.top, |                                               (float)bottom_screen.left, (float)bottom_screen.top, | ||||||
|  | @ -1076,6 +1104,16 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f | ||||||
|                                  ((float)bottom_screen.left / 2) + ((float)layout.width / 2), |                                  ((float)bottom_screen.left / 2) + ((float)layout.width / 2), | ||||||
|                                  (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, |                                  (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2, | ||||||
|                                  (float)bottom_screen.GetHeight()); |                                  (float)bottom_screen.GetHeight()); | ||||||
|  |             } else if (Settings::values.render_3d == 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) { |             } else if (stereo_single_screen) { | ||||||
|                 DrawSingleScreenStereo(screen_infos[2], screen_infos[2], (float)bottom_screen.left, |                 DrawSingleScreenStereo(screen_infos[2], screen_infos[2], (float)bottom_screen.left, | ||||||
|                                        (float)bottom_screen.top, (float)bottom_screen.GetWidth(), |                                        (float)bottom_screen.top, (float)bottom_screen.GetWidth(), | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue