From 6aed5dde4655f81acecf24bb29214f8962577946 Mon Sep 17 00:00:00 2001 From: SSimco <37044560+SSimco@users.noreply.github.com> Date: Thu, 8 Jun 2023 08:51:15 +0300 Subject: [PATCH] Make SDL & OpenGL optional and fix build on Android --- CMakeLists.txt | 24 +++-- cmake/vcpkg_android.cmake | 99 +++++++++++++++++++ dependencies/ih264d/decoder/ih264d_dpb_mgr.c | 7 -- src/CMakeLists.txt | 12 ++- .../HW/Latte/LatteAddrLib/LatteAddrLib.cpp | 8 +- .../Latte/Renderer/OpenGL/OpenGLRenderer.cpp | 5 + src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h | 8 +- .../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 41 +++++++- .../HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 10 +- src/Common/CMakeLists.txt | 2 +- .../ExceptionHandler_posix.cpp | 2 + src/Common/GLInclude/GLInclude.h | 12 ++- src/Common/betype.h | 12 +-- src/Common/platform.h | 3 + src/Common/precompiled.h | 9 +- src/asm/CMakeLists.txt | 2 + src/config/ActiveSettings.h | 4 + src/gui/guiWrapper.h | 2 +- src/imgui/imgui_impl_opengl3.cpp | 5 +- src/input/CMakeLists.txt | 18 +++- src/input/ControllerFactory.cpp | 2 + src/input/api/SDL/SDLControllerProvider.h | 6 +- src/input/emulated/ClassicController.cpp | 4 + src/input/emulated/ProController.cpp | 4 + src/input/emulated/VPADController.cpp | 4 + src/main.cpp | 4 +- src/util/CMakeLists.txt | 10 +- src/util/Fiber/FiberBoost.cpp | 83 ++++++++++++++++ vcpkg.json | 12 ++- 29 files changed, 360 insertions(+), 54 deletions(-) create mode 100644 cmake/vcpkg_android.cmake create mode 100644 src/util/Fiber/FiberBoost.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 26d676bc..bb40f2ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,13 +17,20 @@ if (EXPERIMENTAL_VERSION) endif() if (ENABLE_VCPKG) - if(UNIX AND NOT APPLE) + + if(UNIX AND NOT APPLE AND NOT VCPKG_TARGET_ANDROID) set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_linux") else() set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports") endif() - set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/vcpkg/scripts/buildsystems/vcpkg.cmake" - CACHE STRING "Vcpkg toolchain file") + if(VCPKG_TARGET_ANDROID) + set(ENV{ANDROID_NDK_HOME} ${ANDROID_NDK}) + set(ENV{VCPKG_ROOT} "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/vcpkg") + include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/vcpkg_android.cmake") + else() + set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/vcpkg/scripts/buildsystems/vcpkg.cmake" + CACHE STRING "Vcpkg toolchain file") + endif() # Set this so that all the various find_package() calls don't need an explicit # CONFIG option set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) @@ -103,11 +110,14 @@ option(ENABLE_WXWIDGETS "Build with wxWidgets UI (Currently required)" ON) set(THREADS_PREFER_PTHREAD_FLAG true) find_package(Threads REQUIRED) -find_package(SDL2 REQUIRED) +if(ENABLE_SDL) + find_package(SDL2 REQUIRED) + add_compile_definitions("HAS_SDL=1") +endif() find_package(CURL REQUIRED) find_package(pugixml REQUIRED) find_package(RapidJSON REQUIRED) -find_package(Boost COMPONENTS program_options filesystem nowide REQUIRED) +find_package(Boost COMPONENTS program_options filesystem nowide context REQUIRED) find_package(libzip REQUIRED) find_package(glslang REQUIRED) find_package(ZLIB REQUIRED) @@ -122,7 +132,7 @@ if (NOT TARGET glslang::SPIRV AND TARGET SPIRV) add_library(glslang::SPIRV ALIAS SPIRV) endif() -if (UNIX AND NOT APPLE) +if (UNIX AND NOT APPLE AND NOT ANDROID) find_package(X11 REQUIRED) if (ENABLE_WAYLAND) find_package(Wayland REQUIRED Client) @@ -155,7 +165,7 @@ if (ENABLE_DISCORD_RPC) target_include_directories(discord-rpc INTERFACE ./dependencies/discord-rpc/include) endif() -if(UNIX AND NOT APPLE) +if(UNIX AND NOT APPLE AND NOT ANDROID) if(ENABLE_FERAL_GAMEMODE) add_compile_definitions(ENABLE_FERAL_GAMEMODE) add_subdirectory(dependencies/gamemode EXCLUDE_FROM_ALL) diff --git a/cmake/vcpkg_android.cmake b/cmake/vcpkg_android.cmake new file mode 100644 index 00000000..3f09b111 --- /dev/null +++ b/cmake/vcpkg_android.cmake @@ -0,0 +1,99 @@ +# +# vcpkg_android.cmake +# +# Helper script when using vcpkg with cmake. It should be triggered via the variable VCPKG_TARGET_ANDROID +# +# For example: +# if (VCPKG_TARGET_ANDROID) +# include("cmake/vcpkg_android.cmake") +# endif() +# +# This script will: +# 1 & 2. check the presence of needed env variables: ANDROID_NDK_HOME and VCPKG_ROOT +# 3. set VCPKG_TARGET_TRIPLET according to ANDROID_ABI +# 4. Combine vcpkg and Android toolchains by setting CMAKE_TOOLCHAIN_FILE +# and VCPKG_CHAINLOAD_TOOLCHAIN_FILE + +# Note: VCPKG_TARGET_ANDROID is not an official Vcpkg variable. +# it is introduced for the need of this script + +if (VCPKG_TARGET_ANDROID) + + # + # 1. Check the presence of environment variable ANDROID_NDK_HOME + # + if (NOT DEFINED ENV{ANDROID_NDK_HOME}) + message(FATAL_ERROR " + Please set an environment variable ANDROID_NDK_HOME + For example: + export ANDROID_NDK_HOME=/home/your-account/Android/Sdk/ndk-bundle + Or: + export ANDROID_NDK_HOME=/home/your-account/Android/android-ndk-r21b + ") + endif() + + # + # 2. Check the presence of environment variable VCPKG_ROOT + # + if (NOT DEFINED ENV{VCPKG_ROOT}) + message(FATAL_ERROR " + Please set an environment variable VCPKG_ROOT + For example: + export VCPKG_ROOT=/path/to/vcpkg + ") + endif() + + + # + # 3. Set VCPKG_TARGET_TRIPLET according to ANDROID_ABI + # + # There are four different Android ABI, each of which maps to + # a vcpkg triplet. The following table outlines the mapping from vcpkg architectures to android architectures + # + # |VCPKG_TARGET_TRIPLET | ANDROID_ABI | + # |---------------------------|----------------------| + # |arm64-android | arm64-v8a | + # |arm-android | armeabi-v7a | + # |x64-android | x86_64 | + # |x86-android | x86 | + # + # The variable must be stored in the cache in order to successfully the two toolchains. + # + if (ANDROID_ABI MATCHES "arm64-v8a") + set(VCPKG_TARGET_TRIPLET "arm64-android" CACHE STRING "" FORCE) + elseif(ANDROID_ABI MATCHES "armeabi-v7a") + set(VCPKG_TARGET_TRIPLET "arm-android" CACHE STRING "" FORCE) + elseif(ANDROID_ABI MATCHES "x86_64") + set(VCPKG_TARGET_TRIPLET "x64-android" CACHE STRING "" FORCE) + elseif(ANDROID_ABI MATCHES "x86") + set(VCPKG_TARGET_TRIPLET "x86-android" CACHE STRING "" FORCE) + else() + message(FATAL_ERROR " + Please specify ANDROID_ABI + For example + cmake ... -DANDROID_ABI=armeabi-v7a + + Possible ABIs are: arm64-v8a, armeabi-v7a, x64-android, x86-android + ") + endif() + message("vcpkg_android.cmake: VCPKG_TARGET_TRIPLET was set to ${VCPKG_TARGET_TRIPLET}") + + + # + # 4. Combine vcpkg and Android toolchains + # + + # vcpkg and android both provide dedicated toolchains: + # + # vcpkg_toolchain_file=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake + # android_toolchain_file=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake + # + # When using vcpkg, the vcpkg toolchain shall be specified first. + # However, vcpkg provides a way to preload and additional toolchain, + # with the VCPKG_CHAINLOAD_TOOLCHAIN_FILE option. + set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE $ENV{ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake) + set(CMAKE_TOOLCHAIN_FILE $ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake) + message("vcpkg_android.cmake: CMAKE_TOOLCHAIN_FILE was set to ${CMAKE_TOOLCHAIN_FILE}") + message("vcpkg_android.cmake: VCPKG_CHAINLOAD_TOOLCHAIN_FILE was set to ${VCPKG_CHAINLOAD_TOOLCHAIN_FILE}") + +endif(VCPKG_TARGET_ANDROID) diff --git a/dependencies/ih264d/decoder/ih264d_dpb_mgr.c b/dependencies/ih264d/decoder/ih264d_dpb_mgr.c index ce977d73..0e36cd32 100644 --- a/dependencies/ih264d/decoder/ih264d_dpb_mgr.c +++ b/dependencies/ih264d/decoder/ih264d_dpb_mgr.c @@ -17,9 +17,6 @@ ***************************************************************************** * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore */ -#ifdef __ANDROID__ -#include -#endif #include "ih264_typedefs.h" #include "ih264_macros.h" #include "ih264_platform_macros.h" @@ -902,10 +899,6 @@ WORD32 ih264d_read_mmco_commands(struct _DecStruct * ps_dec) { if (j >= MAX_REF_BUFS) { -#ifdef __ANDROID__ - ALOGE("b/25818142"); - android_errorWriteLog(0x534e4554, "25818142"); -#endif ps_dpb_cmds->u1_num_of_commands = 0; return -1; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a343f5a3..308ceafc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,6 +18,8 @@ elseif(UNIX) VK_USE_PLATFORM_MACOS_MVK VK_USE_PLATFORM_METAL_EXT ) + elseif(ANDROID) + add_compile_definitions(VK_USE_PLATFORM_ANDROID_KHR) else() add_compile_definitions( VK_USE_PLATFORM_XLIB_KHR # legacy. Do we need to support XLIB surfaces? @@ -115,10 +117,16 @@ target_link_libraries(CemuBin PRIVATE CemuGui CemuInput CemuUtil - OpenGL::GL - SDL2::SDL2 ) +if(ENABLE_OPENGL) + target_link_libraries(CemuBin PRIVATE OpenGL::GL) +endif() + +if(ENABLE_SDL) + target_link_libraries(CemuBin PRIVATE SDL2::SDL2) +endif() + if(UNIX AND NOT APPLE) # due to nasm output some linkers will make stack executable # cemu does not require this so we explicity disable it diff --git a/src/Cafe/HW/Latte/LatteAddrLib/LatteAddrLib.cpp b/src/Cafe/HW/Latte/LatteAddrLib/LatteAddrLib.cpp index 60a6e2c4..c111e5af 100644 --- a/src/Cafe/HW/Latte/LatteAddrLib/LatteAddrLib.cpp +++ b/src/Cafe/HW/Latte/LatteAddrLib/LatteAddrLib.cpp @@ -2,7 +2,9 @@ #include "Cafe/HW/Latte/LatteAddrLib/LatteAddrLib.h" #include "Cafe/OS/libs/gx2/GX2_Surface.h" #include - +#if __ANDROID__ +#include +#endif /* Info: @@ -73,7 +75,11 @@ namespace LatteAddrLib uint32 NextPow2(uint32 dim) { +#if __ANDROID__ + return boost::core::bit_ceil(dim); +#else return std::bit_ceil(dim); +#endif } uint32 GetBitsPerPixel(E_HWSURFFMT format, uint32* pElemMode, uint32* pExpandX, uint32* pExpandY) diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp index 7a92f9f9..fdeda42c 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRenderer.cpp @@ -209,6 +209,11 @@ void LoadOpenGLImports() #include "Common/GLInclude/glFunctions.h" #undef GLFUNC } +#elif __ANDROID__ +void LoadOpenGLImports() +{ + cemu_assert_unimplemented(); +} #elif BOOST_OS_LINUX GL_IMPORT _GetOpenGLFunction(void* hLib, PFNGLXGETPROCADDRESSPROC func, const char* name) { diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h index de4f1bb8..b50c5a74 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h @@ -127,12 +127,16 @@ VKFUNC_DEVICE(vkCmdBindPipeline); // swapchain #if BOOST_OS_LINUX +#if __ANDROID__ +VKFUNC_INSTANCE(vkCreateAndroidSurfaceKHR); +#else VKFUNC_INSTANCE(vkCreateXlibSurfaceKHR); VKFUNC_INSTANCE(vkCreateXcbSurfaceKHR); #ifdef HAS_WAYLAND VKFUNC_INSTANCE(vkCreateWaylandSurfaceKHR); -#endif -#endif +#endif // HAS_WAYLAND +#endif // __ANDROID__ +#endif // BOOST_OS_LINUX #if BOOST_OS_WINDOWS VKFUNC_INSTANCE(vkCreateWin32SurfaceKHR); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index f7119b75..166ac016 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -106,15 +106,19 @@ std::vector VulkanRenderer::GetDevices() requiredExtensions.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME); #if BOOST_OS_WINDOWS requiredExtensions.emplace_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); - #elif BOOST_OS_LINUX + #elif BOOST_OS_LINUX + #if __ANDROID__ + requiredExtensions.emplace_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); + #else auto backend = gui_getWindowInfo().window_main.backend; if(backend == WindowHandleInfo::Backend::X11) requiredExtensions.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); #ifdef HAS_WAYLAND else if (backend == WindowHandleInfo::Backend::WAYLAND) requiredExtensions.emplace_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); - #endif - #elif BOOST_OS_MACOS + #endif // HAS_WAYLAND + #endif // __ANDROID__ + #elif BOOST_OS_MACOS requiredExtensions.emplace_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME); #endif @@ -1177,14 +1181,18 @@ std::vector VulkanRenderer::CheckInstanceExtensionSupport(FeatureCo requiredInstanceExtensions.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME); #if BOOST_OS_WINDOWS requiredInstanceExtensions.emplace_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); - #elif BOOST_OS_LINUX + #elif BOOST_OS_LINUX + #if __ANDROID__ + requiredInstanceExtensions.emplace_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); + #else auto backend = gui_getWindowInfo().window_main.backend; if(backend == WindowHandleInfo::Backend::X11) requiredInstanceExtensions.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); #if HAS_WAYLAND else if (backend == WindowHandleInfo::Backend::WAYLAND) requiredInstanceExtensions.emplace_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); - #endif + #endif // HAS_WAYLAND + #endif // __ANDROID__ #elif BOOST_OS_MACOS requiredInstanceExtensions.emplace_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME); #endif @@ -1265,6 +1273,25 @@ VkSurfaceKHR VulkanRenderer::CreateWinSurface(VkInstance instance, HWND hwindow) #endif #if BOOST_OS_LINUX +#if __ANDROID__ +VkSurfaceKHR VulkanRenderer::CreateAndroidSurface(VkInstance instance, ANativeWindow* window) +{ + VkAndroidSurfaceCreateInfoKHR sci{}; + sci.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + sci.flags = 0; + sci.window = window; + + VkSurfaceKHR result; + VkResult err; + if ((err = vkCreateAndroidSurfaceKHR(instance, &sci, nullptr, &result)) != VK_SUCCESS) + { + forceLog_printf("Cannot create an Android Vulkan surface: %d", (sint32)err); + throw std::runtime_error(fmt::format("Cannot create an Android Vulkan surface: {}", err)); + } + + return result; +} +#else VkSurfaceKHR VulkanRenderer::CreateXlibSurface(VkInstance instance, Display* dpy, Window window) { VkXlibSurfaceCreateInfoKHR sci{}; @@ -1322,6 +1349,7 @@ VkSurfaceKHR VulkanRenderer::CreateWaylandSurface(VkInstance instance, wl_displa return result; } #endif // HAS_WAYLAND +#endif // __ANDROID__ #endif // BOOST_OS_LINUX VkSurfaceKHR VulkanRenderer::CreateFramebufferSurface(VkInstance instance, struct WindowHandleInfo& windowInfo) @@ -1329,6 +1357,8 @@ VkSurfaceKHR VulkanRenderer::CreateFramebufferSurface(VkInstance instance, struc #if BOOST_OS_WINDOWS return CreateWinSurface(instance, windowInfo.hwnd); #elif BOOST_OS_LINUX +#if __ANDROID__ +#else if(windowInfo.backend == WindowHandleInfo::Backend::X11) return CreateXlibSurface(instance, windowInfo.xlib_display, windowInfo.xlib_window); #ifdef HAS_WAYLAND @@ -1336,6 +1366,7 @@ VkSurfaceKHR VulkanRenderer::CreateFramebufferSurface(VkInstance instance, struc return CreateWaylandSurface(instance, windowInfo.display, windowInfo.surface); #endif return {}; +#endif // __ANDROID__ #elif BOOST_OS_MACOS return CreateCocoaSurface(instance, windowInfo.handle); #endif diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h index 147b6c15..93e582e7 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h @@ -199,12 +199,16 @@ public: static VkSurfaceKHR CreateWinSurface(VkInstance instance, HWND hwindow); #endif #if BOOST_OS_LINUX +#if __ANDROID__ + static VkSurfaceKHR CreateAndroidSurface(VkInstance instance, ANativeWindow* window); +#else static VkSurfaceKHR CreateXlibSurface(VkInstance instance, Display* dpy, Window window); static VkSurfaceKHR CreateXcbSurface(VkInstance instance, xcb_connection_t* connection, xcb_window_t window); - #ifdef HAS_WAYLAND +#ifdef HAS_WAYLAND static VkSurfaceKHR CreateWaylandSurface(VkInstance instance, wl_display* display, wl_surface* surface); - #endif -#endif +#endif // HAS_WAYLAND +#endif // __ANDROID__ +#endif // BOOST_OS_LINUX static VkSurfaceKHR CreateFramebufferSurface(VkInstance instance, struct WindowHandleInfo& windowInfo); diff --git a/src/Common/CMakeLists.txt b/src/Common/CMakeLists.txt index 7ed3d67a..4442501b 100644 --- a/src/Common/CMakeLists.txt +++ b/src/Common/CMakeLists.txt @@ -66,7 +66,7 @@ target_link_libraries(CemuCommon PRIVATE glm::glm ) -if (UNIX AND NOT APPLE) +if (UNIX AND NOT APPLE AND NOT ANDROID) target_link_libraries(CemuCommon PRIVATE X11::X11 X11::Xrender X11::Xutil) endif() diff --git a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp index 34430e37..61809680 100644 --- a/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp +++ b/src/Common/ExceptionHandler/ExceptionHandler_posix.cpp @@ -61,6 +61,7 @@ void DemangleAndPrintBacktrace(char** backtrace, size_t size) // handle signals that would dump core, print stacktrace and then dump depending on config void handlerDumpingSignal(int sig, siginfo_t *info, void *context) { +#if !__ANDROID__ if(!CrashLog_Create()) return; // give up if crashlog was already created @@ -118,6 +119,7 @@ void handlerDumpingSignal(int sig, siginfo_t *info, void *context) raise(sig); return; } +#endif // __ANDROID__ // exit process ignoring all issues _Exit(1); } diff --git a/src/Common/GLInclude/GLInclude.h b/src/Common/GLInclude/GLInclude.h index 6f5d33db..b68a7a7e 100644 --- a/src/Common/GLInclude/GLInclude.h +++ b/src/Common/GLInclude/GLInclude.h @@ -6,8 +6,12 @@ #include "wglext.h" #endif -#if BOOST_OS_LINUX > 0 - +#if BOOST_OS_LINUX +#if __ANDROID__ +#define EGL_EGL_PROTOTYPES 0 +#include "egl.h" +#undef EGL_EGL_PROTOTYPES +#else // from Xlib #define Bool int #define Status int @@ -33,8 +37,8 @@ typedef struct __GLXFBConfigRec *GLXFBConfig; #undef Status #undef True #undef False - -#endif +#endif // __ANDROID__ +#endif // BOOST_OS_LINUX #define GLFUNC(__type, __name) extern __type __name; #define EGLFUNC(__type, __name) extern __type __name; diff --git a/src/Common/betype.h b/src/Common/betype.h index e684fb93..da5ff045 100644 --- a/src/Common/betype.h +++ b/src/Common/betype.h @@ -165,36 +165,36 @@ public: return tmp; } - betype& operator^=(const betype& v) requires std::integral + betype& operator^=(const betype& v) requires std::is_integral_v { m_value ^= v.m_value; return *this; } - betype& operator>>=(std::size_t idx) requires std::integral + betype& operator>>=(std::size_t idx) requires std::is_integral_v { m_value = SwapEndian(T(value() >> idx)); return *this; } - betype& operator<<=(std::size_t idx) requires std::integral + betype& operator<<=(std::size_t idx) requires std::is_integral_v { m_value = SwapEndian(T(value() << idx)); return *this; } - betype operator~() const requires std::integral + betype operator~() const requires std::is_integral_v { return from_bevalue(T(~m_value)); } - betype& operator++() requires std::integral + betype& operator++() requires std::is_integral_v { m_value = SwapEndian(T(value() + 1)); return *this; } - betype& operator--() requires std::integral + betype& operator--() requires std::is_integral_v { m_value = SwapEndian(T(value() - 1)); return *this; diff --git a/src/Common/platform.h b/src/Common/platform.h index 3f480f43..25006ecb 100644 --- a/src/Common/platform.h +++ b/src/Common/platform.h @@ -5,6 +5,9 @@ #if BOOST_OS_WINDOWS #include "Common/windows/platform.h" +#elif __ANDROID__ +#include +#include "Common/unix/platform.h" #elif BOOST_OS_LINUX #include #include diff --git a/src/Common/precompiled.h b/src/Common/precompiled.h index 939e3ec4..efa29487 100644 --- a/src/Common/precompiled.h +++ b/src/Common/precompiled.h @@ -74,7 +74,6 @@ #include #include #include -#include #include #include @@ -450,16 +449,24 @@ inline std::string_view _utf8Wrapper(std::u8string_view input) // convert fs::path to utf8 encoded string inline std::string _pathToUtf8(const fs::path& path) { +#if __ANDROID__ + return path.generic_string(); +#else std::u8string strU8 = path.generic_u8string(); std::string v((const char*)strU8.data(), strU8.size()); return v; +#endif // __ANDROID__ } // convert utf8 encoded string to fs::path inline fs::path _utf8ToPath(std::string_view input) { +#if __ANDROID__ + return fs::path(input); +#else std::basic_string_view v((char8_t*)input.data(), input.size()); return fs::path(v); +#endif // __ANDROID__ } class RunAtCemuBoot // -> replaces this with direct function calls. Linkers other than MSVC may optimize way object files entirely if they are not referenced from outside. So a source file self-registering using this would be causing issues diff --git a/src/asm/CMakeLists.txt b/src/asm/CMakeLists.txt index 5d9f84c2..fa9f74a9 100644 --- a/src/asm/CMakeLists.txt +++ b/src/asm/CMakeLists.txt @@ -16,6 +16,8 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") set_property(TARGET CemuAsm PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + elseif(ANDROID) + set(CMAKE_ASM_NASM_COMPILE_OBJECT " -g dwarf2 -f elf64 -o ") else() # NASM diff --git a/src/config/ActiveSettings.h b/src/config/ActiveSettings.h index 678c3966..4ca6caee 100644 --- a/src/config/ActiveSettings.h +++ b/src/config/ActiveSettings.h @@ -24,8 +24,12 @@ private: } static fs::path GetPath(const fs::path& path, std::string_view p) { +#if __ANDROID__ + return path / fs::path(p); +#else std::basic_string_view s((const char8_t*)p.data(), p.size()); return path / fs::path(s); +#endif // __ANDROID__ } static fs::path GetPath(const fs::path& path) { diff --git a/src/gui/guiWrapper.h b/src/gui/guiWrapper.h index 90d2ffae..cfa53b68 100644 --- a/src/gui/guiWrapper.h +++ b/src/gui/guiWrapper.h @@ -6,7 +6,7 @@ struct WindowHandleInfo { #if BOOST_OS_WINDOWS std::atomic hwnd; -#elif BOOST_OS_LINUX +#elif BOOST_OS_LINUX && !__ANDROID__ enum class Backend { X11, diff --git a/src/imgui/imgui_impl_opengl3.cpp b/src/imgui/imgui_impl_opengl3.cpp index 96cf6ce7..44020f1c 100644 --- a/src/imgui/imgui_impl_opengl3.cpp +++ b/src/imgui/imgui_impl_opengl3.cpp @@ -95,6 +95,7 @@ #endif #endif +/* // GL includes #if defined(IMGUI_IMPL_OPENGL_ES2) #include @@ -119,10 +120,10 @@ //#include IMGUI_IMPL_OPENGL_LOADER_CUSTOM"glext.h""glext.h" #endif #endif - +*/ // Desktop GL has glDrawElementsBaseVertex() which GL ES and WebGL don't have. #if defined(IMGUI_IMPL_OPENGL_ES2) || defined(IMGUI_IMPL_OPENGL_ES3) -#define IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX 0 +#define IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX 1 // 0 #else #define IMGUI_IMPL_OPENGL_HAS_DRAW_WITH_BASE_VERTEX 1 #endif diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index 8fc29044..5fed8891 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -15,10 +15,6 @@ add_library(CemuInput api/DSU/DSUControllerProvider.h api/DSU/DSUMessages.h api/DSU/DSUMessages.cpp - api/SDL/SDLController.cpp - api/SDL/SDLControllerProvider.cpp - api/SDL/SDLController.h - api/SDL/SDLControllerProvider.h api/Keyboard/KeyboardControllerProvider.h api/Keyboard/KeyboardControllerProvider.cpp api/Keyboard/KeyboardController.cpp @@ -73,6 +69,15 @@ if(WIN32) ) endif() +if(ENABLE_SDL) + target_sources(CemuInput PRIVATE + api/SDL/SDLController.cpp + api/SDL/SDLControllerProvider.cpp + api/SDL/SDLController.h + api/SDL/SDLControllerProvider.h + ) +endif() + target_include_directories(CemuInput PUBLIC "../") target_link_libraries(CemuInput PRIVATE @@ -85,5 +90,8 @@ target_link_libraries(CemuInput PRIVATE Boost::program_options glm::glm pugixml::pugixml - SDL2::SDL2 ) + +if(ENABLE_SDL) + target_link_libraries(CemuInput PRIVATE SDL2::SDL2) +endif() diff --git a/src/input/ControllerFactory.cpp b/src/input/ControllerFactory.cpp index 70a85a2d..18fa297a 100644 --- a/src/input/ControllerFactory.cpp +++ b/src/input/ControllerFactory.cpp @@ -5,7 +5,9 @@ #include "input/emulated/ClassicController.h" #include "input/emulated/WiimoteController.h" +#if HAS_SDL #include "input/api/SDL/SDLController.h" +#endif // HAS_SDL #include "input/api/Keyboard/KeyboardController.h" #include "input/api/DSU/DSUController.h" #include "input/api/GameCube/GameCubeController.h" diff --git a/src/input/api/SDL/SDLControllerProvider.h b/src/input/api/SDL/SDLControllerProvider.h index b736ba75..4101bb7a 100644 --- a/src/input/api/SDL/SDLControllerProvider.h +++ b/src/input/api/SDL/SDLControllerProvider.h @@ -1,11 +1,9 @@ #pragma once +#if HAS_SDL #include #include "input/motion/MotionHandler.h" #include "input/api/ControllerProvider.h" -#ifndef HAS_SDL -#define HAS_SDL 1 -#endif static bool operator==(const SDL_JoystickGUID& g1, const SDL_JoystickGUID& g2) { @@ -52,3 +50,5 @@ private: std::array m_motion_tracking{}; }; + +#endif // HAS_SDL diff --git a/src/input/emulated/ClassicController.cpp b/src/input/emulated/ClassicController.cpp index e218cded..ac387193 100644 --- a/src/input/emulated/ClassicController.cpp +++ b/src/input/emulated/ClassicController.cpp @@ -1,7 +1,9 @@ #include "input/emulated/ClassicController.h" #include "input/api/Controller.h" +#if HAS_SDL #include "input/api/SDL/SDLController.h" +#endif // HAS_SDL ClassicController::ClassicController(size_t player_index) : WPADController(player_index, kDataFormat_CLASSIC) @@ -130,6 +132,7 @@ bool ClassicController::set_default_mapping(const std::shared_ptr> mapping; switch (controller->api()) { +#if HAS_SDL case InputAPI::SDLController: { const auto sdl_controller = std::static_pointer_cast(controller); if (sdl_controller->get_guid() == SDLController::kLeftJoyCon) @@ -206,6 +209,7 @@ bool ClassicController::set_default_mapping(const std::shared_ptr& c std::vector> mapping; switch (controller->api()) { +#if HAS_SDL case InputAPI::SDLController: { const auto sdl_controller = std::static_pointer_cast(controller); if (sdl_controller->get_guid() == SDLController::kLeftJoyCon) @@ -219,6 +222,7 @@ bool ProController::set_default_mapping(const std::shared_ptr& c } break; } +#endif // HAS_SDL case InputAPI::XInput: { mapping = diff --git a/src/input/emulated/VPADController.cpp b/src/input/emulated/VPADController.cpp index eff221ef..a8395632 100644 --- a/src/input/emulated/VPADController.cpp +++ b/src/input/emulated/VPADController.cpp @@ -1,6 +1,8 @@ #include "input/emulated/VPADController.h" #include "input/api/Controller.h" +#if HAS_SDL #include "input/api/SDL/SDLController.h" +#endif // HAS_SDL #include "gui/guiWrapper.h" #include "input/InputManager.h" #include "Cafe/HW/Latte/Core/Latte.h" @@ -510,6 +512,7 @@ bool VPADController::set_default_mapping(const std::shared_ptr& std::vector> mapping; switch (controller->api()) { +#if HAS_SDL case InputAPI::SDLController: { const auto sdl_controller = std::static_pointer_cast(controller); if (sdl_controller->get_guid() == SDLController::kLeftJoyCon) @@ -633,6 +636,7 @@ bool VPADController::set_default_mapping(const std::shared_ptr& } break; } +#endif // HAS_SDL case InputAPI::XInput: { mapping = diff --git a/src/main.cpp b/src/main.cpp index aba8c811..cf7f7c65 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,8 +31,10 @@ #pragma comment(lib,"Dbghelp.lib") #endif +#if HAS_SDL #define SDL_MAIN_HANDLED #include +#endif #if BOOST_OS_LINUX #define _putenv(__s) putenv((char*)(__s)) @@ -329,7 +331,7 @@ int main(int argc, char* argv[]) int main(int argc, char *argv[]) { -#if BOOST_OS_LINUX +#if BOOST_OS_LINUX && !__ANDROID__ XInitThreads(); #endif if (!LaunchSettings::HandleCommandline(argc, argv)) diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index f1bb09a6..599db860 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -74,7 +74,11 @@ if(WIN32) target_sources(CemuUtil PRIVATE MemMapper/MemMapperWin.cpp) target_sources(CemuUtil PRIVATE SystemInfo/SystemInfoWin.cpp) elseif(UNIX) - target_sources(CemuUtil PRIVATE Fiber/FiberUnix.cpp) + if(ANDROID) + target_sources(CemuUtil PRIVATE Fiber/FiberBoost.cpp) + else() + target_sources(CemuUtil PRIVATE Fiber/FiberUnix.cpp) + endif() target_sources(CemuUtil PRIVATE MemMapper/MemMapperUnix.cpp) target_sources(CemuUtil PRIVATE SystemInfo/SystemInfoUnix.cpp) if(NOT APPLE) @@ -90,6 +94,10 @@ set_property(TARGET CemuUtil PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$ + +#include "Fiber.h" + +static constexpr size_t stackSize = 2 * 1024 * 1024; + +struct FiberImpl +{ + bool isThread = false; + void* userParam; + void* stack; + std::function entryPoint; + boost::context::detail::fcontext_t context{}; + FiberImpl* previousFiber; + FiberImpl() + { + stack = malloc(stackSize); + } + static void start(boost::context::detail::transfer_t transfer) + { + FiberImpl* fiber = static_cast(transfer.data); + fiber->previousFiber->context = transfer.fctx; + fiber->previousFiber = nullptr; + fiber->entryPoint(fiber->userParam); + } + ~FiberImpl() + { + free(stack); + } +}; +thread_local Fiber* sCurrentFiber{}; + +Fiber::Fiber(void (*FiberEntryPoint)(void* userParam), void* userParam, void* privateData) + : m_privateData(privateData) +{ + FiberImpl* impl = new FiberImpl; + impl->entryPoint = FiberEntryPoint; + impl->userParam = userParam; + impl->context = boost::context::detail::make_fcontext(reinterpret_cast(impl->stack) + stackSize, stackSize, FiberImpl::start); + m_implData = impl; +} + +Fiber::Fiber(void* privateData) + : m_privateData(privateData) +{ + m_implData = new FiberImpl; +} + +Fiber::~Fiber() +{ + delete static_cast(m_implData); +} + +Fiber* Fiber::PrepareCurrentThread(void* privateData) +{ + sCurrentFiber = new Fiber(privateData); + return sCurrentFiber; +} + +void Fiber::Switch(Fiber& targetFiber) +{ + if (&targetFiber == sCurrentFiber) + { + return; + } + FiberImpl* _currentFiber = static_cast(sCurrentFiber->m_implData); + FiberImpl* _targetFiber = static_cast(targetFiber.m_implData); + _targetFiber->previousFiber = _currentFiber; + sCurrentFiber = &targetFiber; + auto transfer = boost::context::detail::jump_fcontext(_targetFiber->context, _targetFiber); + if (_currentFiber->previousFiber == nullptr) + { + return; + } + _currentFiber->previousFiber->context = transfer.fctx; + _currentFiber->previousFiber->previousFiber = nullptr; +} + +void* Fiber::GetFiberPrivateData() +{ + return sCurrentFiber->m_privateData; +} diff --git a/vcpkg.json b/vcpkg.json index d0facf8b..e83d3bcc 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -11,7 +11,10 @@ "default-features": false }, "rapidjson", - "sdl2", + { + "name": "sdl2", + "platform": "!android" + }, "boost-tokenizer", "boost-container", "boost-program-options", @@ -24,6 +27,10 @@ "boost-ptr-container", "boost-property-tree", "boost-static-string", + { + "name": "boost-context", + "platform" : "android" + }, "boost-random", "fmt", "libpng", @@ -35,7 +42,8 @@ "zstd", { "name": "wxwidgets", - "default-features": false + "default-features": false, + "platform": "!android" }, "openssl", {