#include "VRBase.h" #include #include #include #include #if defined(ANDROID) && defined(OPENXR) #include #ifdef OPENXR_PLATFORM_PICO enum ConfigsSetEXT { UNREAL_VERSION = 0, TRACKING_ORIGIN, OPENGL_NOERROR, ENABLE_SIX_DOF, PRESENTATION_FLAG, ENABLE_CPT, PLATFORM, FOVEATION_LEVEL, SET_DISPLAY_RATE = 8, MRC_TEXTURE_ID = 9, }; enum PxrTrackingDof { PXR_TRACKING_3DOF = 0, PXR_TRACKING_6DOF = 1 }; typedef XrResult (XRAPI_PTR *PFN_xrSetEngineVersionPico)(XrInstance instance,const char* version); typedef XrResult (XRAPI_PTR *PFN_xrStartCVControllerThreadPico)(XrInstance instance,int headSensorState, int handSensorState); typedef XrResult (XRAPI_PTR *PFN_xrStopCVControllerThreadPico)(XrInstance instance,int headSensorState, int handSensorState); typedef XrResult (XRAPI_PTR *PFN_xrSetConfigPICO) (XrSession instance, enum ConfigsSetEXT configIndex, char* configData); PFN_xrSetConfigPICO pfnXrSetConfigPICO = nullptr; PFN_xrSetEngineVersionPico pfnXrSetEngineVersionPico = nullptr; PFN_xrStartCVControllerThreadPico pfnXrStartCVControllerThreadPico = nullptr; PFN_xrStopCVControllerThreadPico pfnXrStopCVControllerThreadPico = nullptr; #endif static engine_t vr_engine; int vr_initialized = 0; void VR_Init( ovrJava java, bool useVulkan ) { if (vr_initialized) return; ovrApp_Clear(&vr_engine.appState); PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR; xrGetInstanceProcAddr( XR_NULL_HANDLE, "xrInitializeLoaderKHR", (PFN_xrVoidFunction*)&xrInitializeLoaderKHR); if (xrInitializeLoaderKHR != NULL) { XrLoaderInitInfoAndroidKHR loaderInitializeInfoAndroid; memset(&loaderInitializeInfoAndroid, 0, sizeof(loaderInitializeInfoAndroid)); loaderInitializeInfoAndroid.type = XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR; loaderInitializeInfoAndroid.next = NULL; loaderInitializeInfoAndroid.applicationVM = java.Vm; loaderInitializeInfoAndroid.applicationContext = java.ActivityObject; xrInitializeLoaderKHR((XrLoaderInitInfoBaseHeaderKHR*)&loaderInitializeInfoAndroid); } std::vector extensions; if (useVulkan) { extensions.push_back(XR_KHR_VULKAN_ENABLE_EXTENSION_NAME); } else { extensions.push_back(XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME); } extensions.push_back(XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME); #ifdef OPENXR_HAS_PERFORMANCE_EXTENSION extensions.push_back(XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME); extensions.push_back(XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME); #endif #ifdef OPENXR_PLATFORM_PICO extensions.push_back(XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME); extensions.push_back("XR_PICO_android_controller_function_ext_enable"); extensions.push_back("XR_PICO_view_state_ext_enable"); extensions.push_back("XR_PICO_frame_end_info_ext"); extensions.push_back("XR_PICO_configs_ext"); extensions.push_back("XR_PICO_reset_sensor"); #endif // Create the OpenXR instance. XrApplicationInfo appInfo; memset(&appInfo, 0, sizeof(appInfo)); strcpy(appInfo.applicationName, java.AppName); strcpy(appInfo.engineName, java.AppName); appInfo.applicationVersion = java.AppVersion; appInfo.engineVersion = java.AppVersion; appInfo.apiVersion = XR_CURRENT_API_VERSION; XrInstanceCreateInfo instanceCreateInfo; memset(&instanceCreateInfo, 0, sizeof(instanceCreateInfo)); instanceCreateInfo.type = XR_TYPE_INSTANCE_CREATE_INFO; #ifdef OPENXR_PLATFORM_PICO XrInstanceCreateInfoAndroidKHR instanceCreateInfoAndroid = {XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR}; instanceCreateInfoAndroid.applicationVM = java.Vm; instanceCreateInfoAndroid.applicationActivity = java.ActivityObject; instanceCreateInfo.next = (XrBaseInStructure*)&instanceCreateInfoAndroid; #else instanceCreateInfo.next = NULL; #endif instanceCreateInfo.createFlags = 0; instanceCreateInfo.applicationInfo = appInfo; instanceCreateInfo.enabledApiLayerCount = 0; instanceCreateInfo.enabledApiLayerNames = NULL; instanceCreateInfo.enabledExtensionCount = extensions.size(); instanceCreateInfo.enabledExtensionNames = extensions.data(); XrResult initResult; OXR(initResult = xrCreateInstance(&instanceCreateInfo, &vr_engine.appState.Instance)); if (initResult != XR_SUCCESS) { ALOGE("Failed to create XR instance: %d.", initResult); exit(1); } #ifdef OPENXR_PLATFORM_PICO xrGetInstanceProcAddr(vr_engine.appState.Instance, "xrSetEngineVersionPico", (PFN_xrVoidFunction*)(&pfnXrSetEngineVersionPico)); xrGetInstanceProcAddr(vr_engine.appState.Instance, "xrStartCVControllerThreadPico", (PFN_xrVoidFunction*)(&pfnXrStartCVControllerThreadPico)); xrGetInstanceProcAddr(vr_engine.appState.Instance, "xrStopCVControllerThreadPico", (PFN_xrVoidFunction*)(&pfnXrStopCVControllerThreadPico)); xrGetInstanceProcAddr(vr_engine.appState.Instance,"xrSetConfigPICO", (PFN_xrVoidFunction*)(&pfnXrSetConfigPICO)); if (pfnXrSetEngineVersionPico != nullptr) pfnXrSetEngineVersionPico(vr_engine.appState.Instance, "2.8.0.1"); if (pfnXrStartCVControllerThreadPico != nullptr) pfnXrStartCVControllerThreadPico(vr_engine.appState.Instance, PXR_TRACKING_6DOF, PXR_TRACKING_6DOF); #endif XrInstanceProperties instanceInfo; instanceInfo.type = XR_TYPE_INSTANCE_PROPERTIES; instanceInfo.next = NULL; OXR(xrGetInstanceProperties(vr_engine.appState.Instance, &instanceInfo)); ALOGV( "Runtime %s: Version : %u.%u.%u", instanceInfo.runtimeName, XR_VERSION_MAJOR(instanceInfo.runtimeVersion), XR_VERSION_MINOR(instanceInfo.runtimeVersion), XR_VERSION_PATCH(instanceInfo.runtimeVersion)); XrSystemGetInfo systemGetInfo; memset(&systemGetInfo, 0, sizeof(systemGetInfo)); systemGetInfo.type = XR_TYPE_SYSTEM_GET_INFO; systemGetInfo.next = NULL; systemGetInfo.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY; XrSystemId systemId; OXR(initResult = xrGetSystem(vr_engine.appState.Instance, &systemGetInfo, &systemId)); if (initResult != XR_SUCCESS) { ALOGE("Failed to get system."); exit(1); } // Get the graphics requirements. if (useVulkan) { PFN_xrGetVulkanGraphicsRequirementsKHR pfnGetVulkanGraphicsRequirementsKHR = NULL; OXR(xrGetInstanceProcAddr( vr_engine.appState.Instance, "xrGetVulkanGraphicsRequirementsKHR", (PFN_xrVoidFunction*)(&pfnGetVulkanGraphicsRequirementsKHR))); XrGraphicsRequirementsVulkanKHR graphicsRequirements = {}; graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR; OXR(pfnGetVulkanGraphicsRequirementsKHR(vr_engine.appState.Instance, systemId, &graphicsRequirements)); } else { PFN_xrGetOpenGLESGraphicsRequirementsKHR pfnGetOpenGLESGraphicsRequirementsKHR = NULL; OXR(xrGetInstanceProcAddr( vr_engine.appState.Instance, "xrGetOpenGLESGraphicsRequirementsKHR", (PFN_xrVoidFunction*)(&pfnGetOpenGLESGraphicsRequirementsKHR))); XrGraphicsRequirementsOpenGLESKHR graphicsRequirements = {}; graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR; OXR(pfnGetOpenGLESGraphicsRequirementsKHR(vr_engine.appState.Instance, systemId, &graphicsRequirements)); } vr_engine.appState.MainThreadTid = gettid(); vr_engine.appState.SystemId = systemId; vr_engine.java = java; vr_engine.useVulkan = useVulkan; vr_initialized = 1; } void VR_Destroy( engine_t* engine ) { if (engine == &vr_engine) { #ifdef OPENXR_PLATFORM_PICO if (pfnXrStopCVControllerThreadPico != nullptr) { pfnXrStopCVControllerThreadPico(engine->appState.Instance, PXR_TRACKING_6DOF, PXR_TRACKING_6DOF); } #endif xrDestroyInstance(engine->appState.Instance); ovrApp_Destroy(&engine->appState); } } void VR_EnterVR( engine_t* engine, XrGraphicsBindingVulkanKHR* graphicsBindingVulkan ) { if (engine->appState.Session) { ALOGE("VR_EnterVR called with existing session"); return; } // Create the OpenXR Session. XrSessionCreateInfo sessionCreateInfo = {}; XrGraphicsBindingOpenGLESAndroidKHR graphicsBindingAndroidGLES = {}; memset(&sessionCreateInfo, 0, sizeof(sessionCreateInfo)); if (engine->useVulkan) { sessionCreateInfo.next = graphicsBindingVulkan; } else { graphicsBindingAndroidGLES.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR; graphicsBindingAndroidGLES.next = NULL; graphicsBindingAndroidGLES.display = eglGetCurrentDisplay(); graphicsBindingAndroidGLES.config = eglGetCurrentSurface(EGL_DRAW); graphicsBindingAndroidGLES.context = eglGetCurrentContext(); sessionCreateInfo.next = &graphicsBindingAndroidGLES; } sessionCreateInfo.type = XR_TYPE_SESSION_CREATE_INFO; sessionCreateInfo.createFlags = 0; sessionCreateInfo.systemId = engine->appState.SystemId; XrResult initResult; OXR(initResult = xrCreateSession(engine->appState.Instance, &sessionCreateInfo, &engine->appState.Session)); if (initResult != XR_SUCCESS) { ALOGE("Failed to create XR session: %d.", initResult); exit(1); } #ifdef OPENXR_PLATFORM_PICO pfnXrSetConfigPICO(engine->appState.Session, TRACKING_ORIGIN, "1"); #endif // Create a space to the first path XrReferenceSpaceCreateInfo spaceCreateInfo = {}; spaceCreateInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO; spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW; spaceCreateInfo.poseInReferenceSpace.orientation.w = 1.0f; OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.HeadSpace)); } void VR_LeaveVR( engine_t* engine ) { if (engine->appState.Session) { OXR(xrDestroySpace(engine->appState.HeadSpace)); // StageSpace is optional. if (engine->appState.StageSpace != XR_NULL_HANDLE) { OXR(xrDestroySpace(engine->appState.StageSpace)); } OXR(xrDestroySpace(engine->appState.FakeStageSpace)); engine->appState.CurrentSpace = XR_NULL_HANDLE; OXR(xrDestroySession(engine->appState.Session)); engine->appState.Session = NULL; } } engine_t* VR_GetEngine( void ) { return &vr_engine; } #endif