From 037310f8dcc2a8d46388371cdfa76dd16e4c9b8d Mon Sep 17 00:00:00 2001 From: Triang3l Date: Mon, 11 Jul 2022 21:45:57 +0300 Subject: [PATCH] [Android] Unified xenia-app with windowed apps and build prerequisites --- .drone.star | 15 +++--- .../xenia/emulator/WindowedAppActivity.java | 3 +- premake5.lua | 11 ++-- src/xenia/app/premake5.lua | 50 +++++++++++++++---- src/xenia/app/xenia_main.cc | 8 +++ src/xenia/cpu/ppc/testing/ppc_testing_main.cc | 2 + src/xenia/cpu/testing/premake5.lua | 9 +++- src/xenia/cpu/testing/util.h | 18 ++++--- src/xenia/gpu/d3d12/premake5.lua | 2 +- src/xenia/gpu/vulkan/premake5.lua | 2 +- src/xenia/hid/hid_demo.cc | 7 +++ src/xenia/hid/premake5.lua | 10 ++-- src/xenia/ui/d3d12/premake5.lua | 2 +- src/xenia/ui/file_picker_android.cc | 37 ++++++++++++++ src/xenia/ui/vulkan/premake5.lua | 2 +- tools/build/premake5.lua | 1 + tools/build/scripts/single_library.lua | 20 ++++++++ tools/build/scripts/test_suite.lua | 20 ++++++-- 18 files changed, 176 insertions(+), 43 deletions(-) create mode 100644 src/xenia/ui/file_picker_android.cc create mode 100644 tools/build/scripts/single_library.lua diff --git a/.drone.star b/.drone.star index 60278044c..194adc533 100644 --- a/.drone.star +++ b/.drone.star @@ -39,37 +39,36 @@ def targets_android(platform): 'mspack', 'snappy', 'xxhash', - 'xenia-core', + 'xenia-app', # 'xenia-app-discord', 'xenia-apu', 'xenia-apu-nop', 'xenia-base', 'xenia-base-tests', + 'xenia-core', 'xenia-cpu', - # 'xenia-cpu-tests', - # 'xenia-cpu-ppc-tests', + 'xenia-cpu-tests', + 'xenia-cpu-ppc-tests', # 'xenia-cpu-backend-x64', # 'xenia-debug-ui', 'xenia-gpu', 'xenia-gpu-shader-compiler', 'xenia-gpu-null', 'xenia-gpu-vulkan', - # 'xenia-gpu-vulkan-trace-viewer', + 'xenia-gpu-vulkan-trace-viewer', 'xenia-gpu-vulkan-trace-dump', 'xenia-hid', - # 'xenia-hid-demo', + 'xenia-hid-demo', 'xenia-hid-nop', 'xenia-kernel', 'xenia-ui', 'xenia-ui-vulkan', - # 'xenia-ui-window-vulkan-demo', + 'xenia-ui-window-vulkan-demo', 'xenia-vfs', 'xenia-vfs-dump', ] if platform == 'Android-x86_64': targets.extend([ - 'xenia-cpu-tests', - 'xenia-cpu-ppc-tests', 'xenia-cpu-backend-x64', 'xenia-debug-ui', ]) diff --git a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java index e93baaf0e..323395057 100644 --- a/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java +++ b/android/android_studio_project/app/src/main/java/jp/xenia/emulator/WindowedAppActivity.java @@ -13,8 +13,7 @@ import jp.xenia.XeniaRuntimeException; public abstract class WindowedAppActivity extends Activity { static { - // TODO(Triang3l): Move all demos to libxenia.so. - System.loadLibrary("xenia-ui-window-vulkan-demo"); + System.loadLibrary("xenia-app"); } private final WindowSurfaceOnLayoutChangeListener mWindowSurfaceOnLayoutChangeListener = diff --git a/premake5.lua b/premake5.lua index 1b5a8ec9d..6739d6dba 100644 --- a/premake5.lua +++ b/premake5.lua @@ -141,6 +141,12 @@ filter("platforms:Android-*") systemversion("24") cppstl("c++") staticruntime("On") + -- Hidden visibility is needed to prevent dynamic relocations in FFmpeg + -- AArch64 Neon libavcodec assembly with PIC (accesses extern lookup tables + -- using `adrp` and `add`, without the Global Object Table, expecting that all + -- FFmpeg symbols that aren't a part of the FFmpeg API are hidden by FFmpeg's + -- original build system) by resolving those relocations at link time instead. + visibility("Hidden") links({ "android", "dl", @@ -272,6 +278,7 @@ workspace("xenia") end include("src/xenia") + include("src/xenia/app") include("src/xenia/app/discord") include("src/xenia/apu") include("src/xenia/apu/nop") @@ -293,10 +300,6 @@ workspace("xenia") include("src/xenia/apu/sdl") include("src/xenia/helper/sdl") include("src/xenia/hid/sdl") - - -- TODO(Triang3l): src/xenia/app has a dependency on xenia-helper-sdl, bring - -- it back later. - include("src/xenia/app") end if os.istarget("windows") then diff --git a/src/xenia/app/premake5.lua b/src/xenia/app/premake5.lua index 3f5133d2d..86fcef758 100644 --- a/src/xenia/app/premake5.lua +++ b/src/xenia/app/premake5.lua @@ -4,25 +4,18 @@ include(project_root.."/tools/build") group("src") project("xenia-app") uuid("d7e98620-d007-4ad8-9dbd-b47c8853a17f") - kind("WindowedApp") - targetname("xenia") language("C++") links({ - "xenia-app-discord", "xenia-apu", "xenia-apu-nop", - "xenia-apu-sdl", "xenia-base", "xenia-core", "xenia-cpu", - "xenia-debug-ui", "xenia-gpu", "xenia-gpu-null", "xenia-gpu-vulkan", - "xenia-helper-sdl", "xenia-hid", "xenia-hid-nop", - "xenia-hid-sdl", "xenia-kernel", "xenia-ui", "xenia-ui-vulkan", @@ -48,7 +41,6 @@ project("xenia-app") }) local_platform_files() files({ - "xenia_main.cc", "../base/main_init_"..platform_suffix..".cc", "../ui/windowed_app_main_"..platform_suffix..".cc", }) @@ -57,19 +49,53 @@ project("xenia-app") project_root, }) + filter(SINGLE_LIBRARY_FILTER) + -- Unified library containing all apps as StaticLibs, not just the main + -- emulator windowed app. + kind("SharedLib") + links({ + "xenia-gpu-vulkan-trace-viewer", + "xenia-hid-demo", + "xenia-ui-window-vulkan-demo", + }) + filter(NOT_SINGLE_LIBRARY_FILTER) + kind("WindowedApp") + + -- `targetname` is broken if building from Gradle, works only for toggling the + -- `lib` prefix, as Gradle uses LOCAL_MODULE_FILENAME, not a derivative of + -- LOCAL_MODULE, to specify the targets to build when executing ndk-build. + filter("platforms:not Android-*") + targetname("xenia") + filter("architecture:x86_64") links({ "xenia-cpu-backend-x64", }) + -- TODO(Triang3l): The emulator itself on Android. + filter("platforms:not Android-*") + files({ + "xenia_main.cc", + }) + filter("platforms:Windows") files({ "main_resources.rc", }) - filter("files:../base/main_init_"..platform_suffix..".cc") + filter({"architecture:x86_64", "files:../base/main_init_"..platform_suffix..".cc"}) vectorextensions("IA32") -- Disable AVX for main_init_win.cc so our AVX check doesn't use AVX instructions. + filter("platforms:not Android-*") + links({ + "xenia-app-discord", + "xenia-apu-sdl", + -- TODO(Triang3l): CPU debugger on Android. + "xenia-debug-ui", + "xenia-helper-sdl", + "xenia-hid-sdl", + }) + filter("platforms:Linux") links({ "X11", @@ -87,6 +113,12 @@ project("xenia-app") "xenia-ui-d3d12", }) + filter({"platforms:Windows", SINGLE_LIBRARY_FILTER}) + links({ + "xenia-gpu-d3d12-trace-viewer", + "xenia-ui-window-d3d12-demo", + }) + filter("platforms:Windows") -- Only create the .user file if it doesn't already exist. local user_file = project_root.."/build/xenia-app.vcxproj.user" diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc index 7986ef79b..15f01a892 100644 --- a/src/xenia/app/xenia_main.cc +++ b/src/xenia/app/xenia_main.cc @@ -36,7 +36,9 @@ // Available audio systems: #include "xenia/apu/nop/nop_audio_system.h" +#if !XE_PLATFORM_ANDROID #include "xenia/apu/sdl/sdl_audio_system.h" +#endif // !XE_PLATFORM_ANDROID #if XE_PLATFORM_WIN32 #include "xenia/apu/xaudio2/xaudio2_audio_system.h" #endif // XE_PLATFORM_WIN32 @@ -50,7 +52,9 @@ // Available input drivers: #include "xenia/hid/nop/nop_hid.h" +#if !XE_PLATFORM_ANDROID #include "xenia/hid/sdl/sdl_hid.h" +#endif // !XE_PLATFORM_ANDROID #if XE_PLATFORM_WIN32 #include "xenia/hid/winkey/winkey_hid.h" #include "xenia/hid/xinput/xinput_hid.h" @@ -253,7 +257,9 @@ std::unique_ptr EmulatorApp::CreateAudioSystem( #if XE_PLATFORM_WIN32 factory.Add("xaudio2"); #endif // XE_PLATFORM_WIN32 +#if !XE_PLATFORM_ANDROID factory.Add("sdl"); +#endif // !XE_PLATFORM_ANDROID factory.Add("nop"); return factory.Create(cvars::apu, processor); } @@ -350,7 +356,9 @@ std::vector> EmulatorApp::CreateInputDrivers( #if XE_PLATFORM_WIN32 factory.Add("xinput", xe::hid::xinput::Create); #endif // XE_PLATFORM_WIN32 +#if !XE_PLATFORM_ANDROID factory.Add("sdl", xe::hid::sdl::Create); +#endif // !XE_PLATFORM_ANDROID #if XE_PLATFORM_WIN32 // WinKey input driver should always be the last input driver added! factory.Add("winkey", xe::hid::winkey::Create); diff --git a/src/xenia/cpu/ppc/testing/ppc_testing_main.cc b/src/xenia/cpu/ppc/testing/ppc_testing_main.cc index 0d54261c4..bcc7e0c6c 100644 --- a/src/xenia/cpu/ppc/testing/ppc_testing_main.cc +++ b/src/xenia/cpu/ppc/testing/ppc_testing_main.cc @@ -425,7 +425,9 @@ bool RunTests(const std::string_view test_name) { int failed_count = 0; int passed_count = 0; +#if XE_ARCH_AMD64 XELOGI("Instruction feature mask {}.", cvars::x64_extension_mask); +#endif // XE_ARCH_AMD64 auto test_path_root = cvars::test_path; std::vector test_files; diff --git a/src/xenia/cpu/testing/premake5.lua b/src/xenia/cpu/testing/premake5.lua index c951243e0..5e70fb3f8 100644 --- a/src/xenia/cpu/testing/premake5.lua +++ b/src/xenia/cpu/testing/premake5.lua @@ -8,10 +8,17 @@ test_suite("xenia-cpu-tests", project_root, ".", { "xenia-base", "xenia-core", "xenia-cpu", - "xenia-cpu-backend-x64", -- TODO(benvanik): cut these dependencies? "xenia-kernel", "xenia-ui", -- needed by xenia-base }, + filtered_links = { + { + filter = 'architecture:x86_64', + links = { + "xenia-cpu-backend-x64", + }, + } + }, }) diff --git a/src/xenia/cpu/testing/util.h b/src/xenia/cpu/testing/util.h index d5c89059c..8f6df2d57 100644 --- a/src/xenia/cpu/testing/util.h +++ b/src/xenia/cpu/testing/util.h @@ -12,6 +12,7 @@ #include +#include "xenia/base/platform.h" #include "xenia/cpu/backend/x64/x64_backend.h" #include "xenia/cpu/hir/hir_builder.h" #include "xenia/cpu/ppc/ppc_context.h" @@ -21,8 +22,6 @@ #include "third_party/catch/include/catch.hpp" -#define XENIA_TEST_X64 1 - namespace xe { namespace cpu { namespace testing { @@ -36,14 +35,17 @@ class TestFunction { memory.reset(new Memory()); memory->Initialize(); -#if XENIA_TEST_X64 { - auto backend = std::make_unique(); - auto processor = std::make_unique(memory.get(), nullptr); - processor->Setup(std::move(backend)); - processors.emplace_back(std::move(processor)); + std::unique_ptr backend; +#if XE_ARCH_AMD64 + backend.reset(new xe::cpu::backend::x64::X64Backend()); +#endif // XE_ARCH + if (backend) { + auto processor = std::make_unique(memory.get(), nullptr); + processor->Setup(std::move(backend)); + processors.emplace_back(std::move(processor)); + } } -#endif // XENIA_TEST_X64 for (auto& processor : processors) { auto module = std::make_unique( diff --git a/src/xenia/gpu/d3d12/premake5.lua b/src/xenia/gpu/d3d12/premake5.lua index 94c7f5b61..f0ee8cc02 100644 --- a/src/xenia/gpu/d3d12/premake5.lua +++ b/src/xenia/gpu/d3d12/premake5.lua @@ -22,7 +22,7 @@ project("xenia-gpu-d3d12") group("src") project("xenia-gpu-d3d12-trace-viewer") uuid("7b5b9fcb-7bf1-43ff-a774-d4c41c8706be") - kind("WindowedApp") + single_library_windowed_app_kind() language("C++") links({ "xenia-apu", diff --git a/src/xenia/gpu/vulkan/premake5.lua b/src/xenia/gpu/vulkan/premake5.lua index 4d8fc4203..90ae7c46e 100644 --- a/src/xenia/gpu/vulkan/premake5.lua +++ b/src/xenia/gpu/vulkan/premake5.lua @@ -26,7 +26,7 @@ project("xenia-gpu-vulkan") group("src") project("xenia-gpu-vulkan-trace-viewer") uuid("86a1dddc-a26a-4885-8c55-cf745225d93e") - kind("WindowedApp") + single_library_windowed_app_kind() language("C++") links({ "xenia-apu", diff --git a/src/xenia/hid/hid_demo.cc b/src/xenia/hid/hid_demo.cc index f4d616f9e..46111fc84 100644 --- a/src/xenia/hid/hid_demo.cc +++ b/src/xenia/hid/hid_demo.cc @@ -21,6 +21,7 @@ #include "xenia/base/clock.h" #include "xenia/base/cvar.h" #include "xenia/base/logging.h" +#include "xenia/base/platform.h" #include "xenia/base/threading.h" #include "xenia/hid/hid_flags.h" #include "xenia/hid/input_system.h" @@ -36,7 +37,9 @@ // Available input drivers: #include "xenia/hid/nop/nop_hid.h" +#if !XE_PLATFORM_ANDROID #include "xenia/hid/sdl/sdl_hid.h" +#endif // !XE_PLATFORM_ANDROID #if XE_PLATFORM_WIN32 #include "xenia/hid/winkey/winkey_hid.h" #include "xenia/hid/xinput/xinput_hid.h" @@ -122,11 +125,13 @@ std::vector> HidDemoApp::CreateInputDrivers( std::vector> drivers; if (cvars::hid.compare("nop") == 0) { drivers.emplace_back(xe::hid::nop::Create(window, kZOrderHidInput)); +#if !XE_PLATFORM_ANDROID } else if (cvars::hid.compare("sdl") == 0) { auto driver = xe::hid::sdl::Create(window, kZOrderHidInput); if (XSUCCEEDED(driver->Setup())) { drivers.emplace_back(std::move(driver)); } +#endif // !XE_PLATFORM_ANDROID #if XE_PLATFORM_WIN32 } else if (cvars::hid.compare("winkey") == 0) { auto driver = xe::hid::winkey::Create(window, kZOrderHidInput); @@ -140,10 +145,12 @@ std::vector> HidDemoApp::CreateInputDrivers( } #endif // XE_PLATFORM_WIN32 } else { +#if !XE_PLATFORM_ANDROID auto sdl_driver = xe::hid::sdl::Create(window, kZOrderHidInput); if (sdl_driver && XSUCCEEDED(sdl_driver->Setup())) { drivers.emplace_back(std::move(sdl_driver)); } +#endif // !XE_PLATFORM_ANDROID #if XE_PLATFORM_WIN32 auto xinput_driver = xe::hid::xinput::Create(window, kZOrderHidInput); if (xinput_driver && XSUCCEEDED(xinput_driver->Setup())) { diff --git a/src/xenia/hid/premake5.lua b/src/xenia/hid/premake5.lua index fd02fef4a..4e961f623 100644 --- a/src/xenia/hid/premake5.lua +++ b/src/xenia/hid/premake5.lua @@ -17,16 +17,14 @@ project("xenia-hid") group("demos") project("xenia-hid-demo") uuid("a56a209c-16d5-4913-85f9-86976fe7fddf") - kind("WindowedApp") + single_library_windowed_app_kind() language("C++") links({ "fmt", "imgui", "xenia-base", - "xenia-helper-sdl", "xenia-hid", "xenia-hid-nop", - "xenia-hid-sdl", "xenia-ui", "xenia-ui-vulkan", }) @@ -41,6 +39,12 @@ project("xenia-hid-demo") project_root, }) + filter("platforms:not Android-*") + links({ + "xenia-helper-sdl", + "xenia-hid-sdl", + }) + filter("platforms:Linux") links({ "SDL2", diff --git a/src/xenia/ui/d3d12/premake5.lua b/src/xenia/ui/d3d12/premake5.lua index 0e33011e5..c0d10096b 100644 --- a/src/xenia/ui/d3d12/premake5.lua +++ b/src/xenia/ui/d3d12/premake5.lua @@ -18,7 +18,7 @@ project("xenia-ui-d3d12") group("demos") project("xenia-ui-window-d3d12-demo") uuid("3b9686a7-0f04-4e17-8b00-aeb78ae1107c") - kind("WindowedApp") + single_library_windowed_app_kind() language("C++") links({ "fmt", diff --git a/src/xenia/ui/file_picker_android.cc b/src/xenia/ui/file_picker_android.cc new file mode 100644 index 000000000..9fe506685 --- /dev/null +++ b/src/xenia/ui/file_picker_android.cc @@ -0,0 +1,37 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2022 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + +#include "xenia/ui/file_picker.h" + +namespace xe { +namespace ui { + +// TODO(Triang3l): An asynchronous file picker with a callback, starting an +// activity for an ACTION_OPEN_DOCUMENT or an ACTION_OPEN_DOCUMENT_TREE intent. +// This intent, however, provides a content URI, not the file path directly. +// Accessing the file via the Storage Access Framework doesn't require the +// READ_EXTERNAL_STORAGE permission, unlike opening a file by its path directly. +// A file descriptor can be opened for the URI using +// Context.getContentResolver().openFileDescriptor (it will return a +// ParcelFileDescriptor, and a FileDescriptor can be obtained using its +// getFileDescriptor() method). + +class AndroidFilePicker : public FilePicker { + public: + bool Show(Window* parent_window) override { return false; } +}; + +std::unique_ptr FilePicker::Create() { + return std::make_unique(); +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/vulkan/premake5.lua b/src/xenia/ui/vulkan/premake5.lua index 454007bcb..bdc6b7458 100644 --- a/src/xenia/ui/vulkan/premake5.lua +++ b/src/xenia/ui/vulkan/premake5.lua @@ -22,7 +22,7 @@ project("xenia-ui-vulkan") group("demos") project("xenia-ui-window-vulkan-demo") uuid("97598f13-3177-454c-8e58-c59e2b6ede27") - kind("WindowedApp") + single_library_windowed_app_kind() language("C++") links({ "fmt", diff --git a/tools/build/premake5.lua b/tools/build/premake5.lua index 2c7f8df6a..6f99284e4 100644 --- a/tools/build/premake5.lua +++ b/tools/build/premake5.lua @@ -5,4 +5,5 @@ include("scripts/force_compile_as_c.lua") include("scripts/force_compile_as_cc.lua") include("scripts/pkg_config.lua") include("scripts/platform_files.lua") +include("scripts/single_library.lua") include("scripts/test_suite.lua") diff --git a/tools/build/scripts/single_library.lua b/tools/build/scripts/single_library.lua new file mode 100644 index 000000000..50f60f2cf --- /dev/null +++ b/tools/build/scripts/single_library.lua @@ -0,0 +1,20 @@ +SINGLE_LIBRARY_PLATFORM_PATTERNS = { + "Android-*", +}; + +SINGLE_LIBRARY_FILTER = + "platforms:" .. table.concat(SINGLE_LIBRARY_PLATFORM_PATTERNS, " or "); +NOT_SINGLE_LIBRARY_FILTER = table.translate( + SINGLE_LIBRARY_PLATFORM_PATTERNS, + function(pattern) + return "platforms:not " .. pattern; + end); + +function single_library_windowed_app_kind() + filter(SINGLE_LIBRARY_FILTER); + kind("StaticLib"); + wholelib("On"); + filter(NOT_SINGLE_LIBRARY_FILTER); + kind("WindowedApp"); + filter({}); +end diff --git a/tools/build/scripts/test_suite.lua b/tools/build/scripts/test_suite.lua index a83e891de..2ef600995 100644 --- a/tools/build/scripts/test_suite.lua +++ b/tools/build/scripts/test_suite.lua @@ -24,8 +24,14 @@ local function combined_test_suite(test_suite_name, project_root, base_path, con libdirs(merge_arrays(config["libdirs"], { project_root.."/"..build_bin, })) - links(merge_arrays(config["links"], { - })) + links(config["links"]) + if config.filtered_links ~= nil then + for _, filtered_links in ipairs(config.filtered_links) do + filter(filtered_links.filter) + links(filtered_links.links) + end + filter({}) + end defines({ "XE_TEST_SUITE_NAME=\""..test_suite_name.."\"", }) @@ -57,8 +63,14 @@ local function split_test_suite(test_suite_name, project_root, base_path, config libdirs(merge_arrays(config["libdirs"], { project_root.."/"..build_bin, })) - links(merge_arrays(config["links"], { - })) + links(config["links"]) + if config.filtered_links ~= nil then + for _, filtered_links in ipairs(config.filtered_links) do + filter(filtered_links.filter) + links(filtered_links.links) + end + filter({}) + end files({ project_root.."/"..build_tools_src.."/test_suite_main.cc", file_path,