Make SDL & OpenGL optional and fix build on Android

This commit is contained in:
SSimco 2023-06-08 08:51:15 +03:00
parent be77df52b9
commit 6aed5dde46
29 changed files with 360 additions and 54 deletions

View File

@ -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)

99
cmake/vcpkg_android.cmake Normal file
View File

@ -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)

View File

@ -17,9 +17,6 @@
*****************************************************************************
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
#ifdef __ANDROID__
#include <log/log.h>
#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;
}

View File

@ -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

View File

@ -2,7 +2,9 @@
#include "Cafe/HW/Latte/LatteAddrLib/LatteAddrLib.h"
#include "Cafe/OS/libs/gx2/GX2_Surface.h"
#include <bit>
#if __ANDROID__
#include <boost/core/bit.hpp>
#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<uint32>(dim);
#endif
}
uint32 GetBitsPerPixel(E_HWSURFFMT format, uint32* pElemMode, uint32* pExpandX, uint32* pExpandY)

View File

@ -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)
{

View File

@ -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);

View File

@ -106,15 +106,19 @@ std::vector<VulkanRenderer::DeviceInfo> 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<const char*> 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

View File

@ -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);

View File

@ -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()

View File

@ -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);
}

View File

@ -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;

View File

@ -165,36 +165,36 @@ public:
return tmp;
}
betype<T>& operator^=(const betype<T>& v) requires std::integral<T>
betype<T>& operator^=(const betype<T>& v) requires std::is_integral_v<T>
{
m_value ^= v.m_value;
return *this;
}
betype<T>& operator>>=(std::size_t idx) requires std::integral<T>
betype<T>& operator>>=(std::size_t idx) requires std::is_integral_v<T>
{
m_value = SwapEndian(T(value() >> idx));
return *this;
}
betype<T>& operator<<=(std::size_t idx) requires std::integral<T>
betype<T>& operator<<=(std::size_t idx) requires std::is_integral_v<T>
{
m_value = SwapEndian(T(value() << idx));
return *this;
}
betype<T> operator~() const requires std::integral<T>
betype<T> operator~() const requires std::is_integral_v<T>
{
return from_bevalue(T(~m_value));
}
betype<T>& operator++() requires std::integral<T>
betype<T>& operator++() requires std::is_integral_v<T>
{
m_value = SwapEndian(T(value() + 1));
return *this;
}
betype<T>& operator--() requires std::integral<T>
betype<T>& operator--() requires std::is_integral_v<T>
{
m_value = SwapEndian(T(value() - 1));
return *this;

View File

@ -5,6 +5,9 @@
#if BOOST_OS_WINDOWS
#include "Common/windows/platform.h"
#elif __ANDROID__
#include <byteswap.h>
#include "Common/unix/platform.h"
#elif BOOST_OS_LINUX
#include <byteswap.h>
#include <X11/Xlib.h>

View File

@ -74,7 +74,6 @@
#include <type_traits>
#include <optional>
#include <span>
#include <ranges>
#include <boost/predef.h>
#include <boost/nowide/convert.hpp>
@ -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<char8_t> 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

View File

@ -16,6 +16,8 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
set_property(TARGET CemuAsm PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
elseif(ANDROID)
set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> -g dwarf2 -f elf64 -o <OBJECT> <SOURCE>")
else()
# NASM

View File

@ -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<char8_t> s((const char8_t*)p.data(), p.size());
return path / fs::path(s);
#endif // __ANDROID__
}
static fs::path GetPath(const fs::path& path)
{

View File

@ -6,7 +6,7 @@ struct WindowHandleInfo
{
#if BOOST_OS_WINDOWS
std::atomic<HWND> hwnd;
#elif BOOST_OS_LINUX
#elif BOOST_OS_LINUX && !__ANDROID__
enum class Backend
{
X11,

View File

@ -95,6 +95,7 @@
#endif
#endif
/*
// GL includes
#if defined(IMGUI_IMPL_OPENGL_ES2)
#include <GLES2/gl2.h>
@ -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

View File

@ -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()

View File

@ -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"

View File

@ -1,11 +1,9 @@
#pragma once
#if HAS_SDL
#include <SDL2/SDL_joystick.h>
#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<MotionInfoTracking, 8> m_motion_tracking{};
};
#endif // HAS_SDL

View File

@ -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<ControllerBase
std::vector<std::pair<uint64, uint64>> mapping;
switch (controller->api())
{
#if HAS_SDL
case InputAPI::SDLController: {
const auto sdl_controller = std::static_pointer_cast<SDLController>(controller);
if (sdl_controller->get_guid() == SDLController::kLeftJoyCon)
@ -206,6 +209,7 @@ bool ClassicController::set_default_mapping(const std::shared_ptr<ControllerBase
};
}
}
#endif // HAS_SDL
case InputAPI::XInput:
{
mapping =

View File

@ -1,7 +1,9 @@
#include "input/emulated/ProController.h"
#include "input/api/Controller.h"
#if HAS_SDL
#include "input/api/SDL/SDLController.h"
#endif // HAS_SDL
ProController::ProController(size_t player_index)
: WPADController(player_index, kDataFormat_URCC)
@ -135,6 +137,7 @@ bool ProController::set_default_mapping(const std::shared_ptr<ControllerBase>& c
std::vector<std::pair<uint64, uint64>> mapping;
switch (controller->api())
{
#if HAS_SDL
case InputAPI::SDLController: {
const auto sdl_controller = std::static_pointer_cast<SDLController>(controller);
if (sdl_controller->get_guid() == SDLController::kLeftJoyCon)
@ -219,6 +222,7 @@ bool ProController::set_default_mapping(const std::shared_ptr<ControllerBase>& c
}
break;
}
#endif // HAS_SDL
case InputAPI::XInput:
{
mapping =

View File

@ -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<ControllerBase>&
std::vector<std::pair<uint64, uint64>> mapping;
switch (controller->api())
{
#if HAS_SDL
case InputAPI::SDLController: {
const auto sdl_controller = std::static_pointer_cast<SDLController>(controller);
if (sdl_controller->get_guid() == SDLController::kLeftJoyCon)
@ -633,6 +636,7 @@ bool VPADController::set_default_mapping(const std::shared_ptr<ControllerBase>&
}
break;
}
#endif // HAS_SDL
case InputAPI::XInput:
{
mapping =

View File

@ -31,8 +31,10 @@
#pragma comment(lib,"Dbghelp.lib")
#endif
#if HAS_SDL
#define SDL_MAIN_HANDLED
#include <SDL.h>
#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))

View File

@ -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$<$<CON
target_include_directories(CemuUtil PUBLIC "../")
if(ANDROID)
target_link_libraries(CemuUtil PRIVATE Boost::context)
endif()
target_link_libraries(CemuUtil PRIVATE
CemuCommon
CemuConfig

View File

@ -0,0 +1,83 @@
#include <boost/context/detail/fcontext.hpp>
#include "Fiber.h"
static constexpr size_t stackSize = 2 * 1024 * 1024;
struct FiberImpl
{
bool isThread = false;
void* userParam;
void* stack;
std::function<void(void*)> 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<FiberImpl*>(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<uint8_t*>(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<FiberImpl*>(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<FiberImpl*>(sCurrentFiber->m_implData);
FiberImpl* _targetFiber = static_cast<FiberImpl*>(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;
}

View File

@ -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",
{