File main.cpp
Go to the documentation of this file
#ifndef ENABLE_MONADO
# include "illixr.hpp"
# ifdef __ANDROID__
# include
# include
# include
# include
# include
# else
# include
# endif
# include
# ifndef NDEBUG
static void sigill_handler(int sig) {
assert(sig == SIGILL && "sigill_handler is for SIGILL");
std::raise(SIGSEGV);
}
static void sigabrt_handler(int sig) {
assert(sig == SIGABRT && "sigabrt_handler is for SIGABRT");
std::raise(SIGSEGV);
}
# endif
static void sigint_handler([[maybe_unused]] int sig) {
assert(sig == SIGINT && "sigint_handler is for SIGINT");
if (runtime_) {
runtime_->stop();
}
}
using namespace ILLIXR;
# ifdef __ANDROID__
# if defined(ILLIXR_ENABLE_BOBA) && defined(ILLIXR_ENABLE_QUEST_CONTROLLERS)
namespace {
std::mutex quest_config_mutex;
std::condition_variable quest_config_cv;
bool quest_config_ready = false;
bool android_destroy_requested = false;
} // namespace
# endif
extern "C" {
// called from Java after permission is granted
JNIEXPORT void JNICALL Java_com_example_ILLIXR_ILLIXRNativeActivity_nativeOnPermissionGranted(JNIEnv* env, jobject activity) { }
// Keep the Java entry point in sync with the native build selection.
JNIEXPORT jboolean JNICALL Java_com_example_ILLIXR_ILLIXRNativeActivity_nativeIsBobaEnabled(JNIEnv*, jobject) {
# if defined(ILLIXR_ENABLE_BOBA) && defined(ILLIXR_ENABLE_QUEST_CONTROLLERS)
return JNI_TRUE;
# else
return JNI_FALSE;
# endif
}
JNIEXPORT void JNICALL Java_com_example_ILLIXR_ILLIXRNativeActivity_nativeConfigure(JNIEnv* env, jobject activity,
jstring server_ip) {
# if defined(ILLIXR_ENABLE_BOBA) && defined(ILLIXR_ENABLE_QUEST_CONTROLLERS)
(void) activity;
if (server_ip == nullptr) {
return;
}
const char* value = env->GetStringUTFChars(server_ip, nullptr);
if (value != nullptr) {
if (value[0] != '\0') {
setenv("ILLIXR_SERVER_IP", value, true);
{
const std::lock_guard<std::mutex> lock{quest_config_mutex};
quest_config_ready = true;
}
quest_config_cv.notify_all();
}
env->ReleaseStringUTFChars(server_ip, value);
}
# endif
}
}
static std::thread runtime_thread_;
static void handle_cmd(struct android_app* app, int32_t cmd) {
# else
int main(int argc, const char* argv[]) {
# endif
# ifdef __ANDROID__
if (cmd == APP_CMD_INIT_WINDOW && !runtime_thread_.joinable()) {
const std::vector<std::string> plugins = {"tcp_network_backend", "udp_network_backend", "network_latency.tx",
"offload_rendering_client", "openxr_interface"};
// EuRoC
setenv("ILLIXR_DATA", "/sdcard/Android/data/com.example.native_activity/mav0", true);
setenv("ILLIXR_LOG", "/sdcard/Android/data/com.example.native_activity/log.txt", true);
setenv("ILLIXR_DEMO_DATA", "/sdcard/Android/data/com.example.native_activity/demo_data", true);
setenv("ILLIXR_OFFLOAD_ENABLE", "False", true);
setenv("ILLIXR_ALIGNMENT_ENABLE", "False", true);
setenv("ILLIXR_ENABLE_VERBOSE_ERRORS", "False", true);
setenv("ILLIXR_RUN_DURATION", "1000000", true);
setenv("ILLIXR_ENABLE_PRE_SLEEP", "False", true);
setenv("ILLIXR_ENABLE_PRE_SLEEP", "False", true);
# ifndef ILLIXR_ENABLE_BOBA
setenv("ILLIXR_TCP_CLIENT_IP", "192.168.8.140", true);
setenv("ILLIXR_TCP_SERVER_IP", "192.168.8.158", true);
setenv("ILLIXR_TCP_CLIENT_PORT", "9000", true);
# endif
setenv("ILLIXR_UDP_CLIENT_PORT", "9002", true);
setenv("ILLIXR_TCP_SERVER_PORT", "9001", true);
setenv("ILLIXR_UDP_SERVER_PORT", "9003", true);
setenv("ILLIXR_IS_CLIENT", "1", true);
setenv("ILLIXR_USE_DEPTH_IMAGES", "0", true);
setenv("ILLIXR_USE_MOTION_VECTOR_IMAGES", "0", true);
# ifndef ILLIXR_ENABLE_BOBA
setenv("ILLIXR_OVERSCAN", "1.1", true); // overscanning
# endif
# else
cxxopts::Options options("ILLIXR", "Main program");
options.show_positional_help();
options.allow_unrecognised_options();
// std::string illixr_data, illixr_demo_data, realsense_cam;
// illixr_data = illixr_demo_data = realsense_cam = "";
// bool offload_enable, alignment_enable, enable_verbose_errors, enable_pre_sleep;
// offload_enable = alignment_enable = enable_verbose_errors = enable_pre_sleep = false;
// long run_dur = 0;
options.add_options()("d,duration", "The duration to run for", cxxopts::value<long>())(
"data", "The data", cxxopts::value<std::string>())("demo_data", "The demo data", cxxopts::value<std::string>())(
"enable_offload", "")("enable_alignment", "")("enable_verbose_errors", "")("enable_pre_sleep", "")(
"h,help", "Produce help message")("realsense_cam", "", cxxopts::value<std::string>()->default_value("auto"))(
"p,plugins", "The plugins to use",
cxxopts::value<std::vector<std::string>>())("y,yaml", "Yaml config file", cxxopts::value<std::string>())("openxr", "");
# if defined(ILLIXR_ENABLE_BOBA) && defined(ILLIXR_ENABLE_QUEST_CONTROLLERS)
options.add_options()("quest-ip", "Quest IP address for native ILLIXR wireless setup", cxxopts::value<std::string>())(
"quest-connect-timeout", "Seconds to wait for ILLIXRApp", cxxopts::value<int>()->default_value("120"));
# endif
auto result = options.parse(argc, argv);
if (result.count("help")) {
std::cout << options.help() << std::endl;
return EXIT_SUCCESS;
}
# endif
# ifndef NDEBUG
std::signal(SIGILL, sigill_handler);
std::signal(SIGABRT, sigabrt_handler);
# endif
std::signal(SIGINT, sigint_handler);
# ifdef __ANDROID__
# if defined(ILLIXR_ENABLE_BOBA) && defined(ILLIXR_ENABLE_QUEST_CONTROLLERS)
runtime_thread_ = std::thread([plugins, app]() {
{
std::unique_lock<std::mutex> lock{quest_config_mutex};
// An existing configuration must not wait for a discovery packet.
const char* server = std::getenv("ILLIXR_SERVER_IP");
const char* legacy_server = std::getenv("ILLIXR_TCP_SERVER_IP");
quest_config_ready = quest_config_ready || (server && *server) || (legacy_server && *legacy_server);
quest_config_cv.wait(lock, []() {
return quest_config_ready || android_destroy_requested;
});
if (android_destroy_requested) {
return;
}
}
ILLIXR::run(plugins, app);
});
# else
runtime_thread_ = std::thread(ILLIXR::run, plugins, app);
# endif
} else if (cmd == APP_CMD_DESTROY) {
# if defined(ILLIXR_ENABLE_BOBA) && defined(ILLIXR_ENABLE_QUEST_CONTROLLERS)
{
const std::lock_guard<std::mutex> lock{quest_config_mutex};
android_destroy_requested = true;
}
quest_config_cv.notify_all();
# endif
if (runtime_) {
runtime_->stop();
}
}
# else
return ILLIXR::run(result);
# endif
}
# ifdef __ANDROID__
void android_main(struct android_app* state) {
state->onAppCmd = handle_cmd;
while (!state->destroyRequested) {
int ident;
int events;
struct android_poll_source* source;
// This loop performs no per-frame work of its own -- rendering happens on
// runtime_thread_ via OpenXR/Vulkan -- so it blocks indefinitely and only wakes to
// dispatch the next lifecycle command or input event.
do {
ident = ALooper_pollOnce(-1, nullptr, &events, (void**) &source);
if (ident >= 0) {
// Process this event.
if (source != nullptr) {
source->process(state, source);
}
}
} while (ident >= 0 && !state->destroyRequested);
}
if (runtime_thread_.joinable()) {
runtime_thread_.join();
}
}
# endif
#endif