Files
ppsspp/Common/VR/VRBase.cpp

239 lines
7.9 KiB
C++
Raw Permalink Normal View History

2022-07-08 14:44:20 +02:00
#include "VRBase.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
2022-07-08 14:44:20 +02:00
#include <string.h>
#include <vector>
2022-07-08 14:44:20 +02:00
#ifndef _WIN32
#include <unistd.h>
#endif
2022-11-04 14:22:42 +01:00
static bool vr_platform[VR_PLATFORM_MAX];
2022-07-08 14:44:20 +02:00
static engine_t vr_engine;
int vr_initialized = 0;
2022-11-06 11:32:42 +01:00
void VR_Init( void* system, const char* name, int version ) {
2022-07-24 14:25:04 +02:00
if (vr_initialized)
return;
2022-07-08 14:44:20 +02:00
if (!XRLoad()) {
return;
}
2022-07-24 14:25:04 +02:00
ovrApp_Clear(&vr_engine.appState);
2022-07-08 14:44:20 +02:00
2022-11-04 13:52:32 +01:00
#ifdef ANDROID
2022-07-24 14:25:04 +02:00
PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR;
2022-11-04 13:52:32 +01:00
xrGetInstanceProcAddr(XR_NULL_HANDLE, "xrInitializeLoaderKHR", (PFN_xrVoidFunction*)&xrInitializeLoaderKHR);
2022-07-24 14:25:04 +02:00
if (xrInitializeLoaderKHR != NULL) {
2022-11-04 13:52:32 +01:00
ovrJava* java = (ovrJava*)system;
XrLoaderInitInfoAndroidKHR loaderInitializeInfo;
memset(&loaderInitializeInfo, 0, sizeof(loaderInitializeInfo));
loaderInitializeInfo.type = XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR;
loaderInitializeInfo.next = NULL;
loaderInitializeInfo.applicationVM = java->Vm;
loaderInitializeInfo.applicationContext = java->ActivityObject;
xrInitializeLoaderKHR((XrLoaderInitInfoBaseHeaderKHR*)&loaderInitializeInfo);
2022-07-24 14:25:04 +02:00
}
2022-11-04 13:52:32 +01:00
#endif
2022-07-08 14:44:20 +02:00
2022-10-17 20:43:58 +02:00
std::vector<const char *> extensions;
2022-11-06 14:37:56 +01:00
if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) {
extensions.push_back(XR_KHR_VULKAN_ENABLE_EXTENSION_NAME);
} else {
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
extensions.push_back(XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME);
#endif
}
extensions.push_back(XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME);
#ifdef ANDROID
if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_INSTANCE)) {
2022-12-07 21:19:33 +01:00
extensions.push_back(XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME);
}
if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_PASSTHROUGH)) {
extensions.push_back(XR_FB_PASSTHROUGH_EXTENSION_NAME);
}
if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_PERFORMANCE)) {
2022-11-04 14:22:42 +01:00
extensions.push_back(XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME);
extensions.push_back(XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME);
}
#endif
2022-07-24 14:25:04 +02:00
// Create the OpenXR instance.
XrApplicationInfo appInfo;
memset(&appInfo, 0, sizeof(appInfo));
2022-11-04 13:52:32 +01:00
strcpy(appInfo.applicationName, name);
strcpy(appInfo.engineName, name);
appInfo.applicationVersion = version;
appInfo.engineVersion = version;
2024-06-03 18:03:57 +02:00
appInfo.apiVersion = XR_API_VERSION_1_0;
2022-07-08 14:44:20 +02:00
2022-07-24 14:25:04 +02:00
XrInstanceCreateInfo instanceCreateInfo;
memset(&instanceCreateInfo, 0, sizeof(instanceCreateInfo));
instanceCreateInfo.type = XR_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.next = NULL;
instanceCreateInfo.createFlags = 0;
instanceCreateInfo.applicationInfo = appInfo;
instanceCreateInfo.enabledApiLayerCount = 0;
instanceCreateInfo.enabledApiLayerNames = NULL;
instanceCreateInfo.enabledExtensionCount = (uint32_t)extensions.size();
instanceCreateInfo.enabledExtensionNames = extensions.data();
2022-07-08 14:44:20 +02:00
2022-11-04 14:22:42 +01:00
#ifdef ANDROID
2022-11-04 14:53:07 +01:00
XrInstanceCreateInfoAndroidKHR instanceCreateInfoAndroid = {XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR};
if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_INSTANCE)) {
2022-11-04 14:22:42 +01:00
ovrJava* java = (ovrJava*)system;
instanceCreateInfoAndroid.applicationVM = java->Vm;
instanceCreateInfoAndroid.applicationActivity = java->ActivityObject;
instanceCreateInfo.next = (XrBaseInStructure*)&instanceCreateInfoAndroid;
}
2022-11-04 13:52:32 +01:00
#endif
2022-07-24 14:25:04 +02:00
XrResult initResult;
OXR(initResult = xrCreateInstance(&instanceCreateInfo, &vr_engine.appState.Instance));
if (initResult != XR_SUCCESS) {
ALOGE("Failed to create XR instance: %d.", initResult);
exit(1);
}
2022-07-08 14:44:20 +02:00
XRLoadInstanceFunctions(vr_engine.appState.Instance);
2022-07-24 14:25:04 +02:00
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));
2022-07-08 14:44:20 +02:00
2022-07-24 14:25:04 +02:00
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;
2022-07-08 14:44:20 +02:00
2022-07-24 14:25:04 +02:00
XrSystemId systemId;
OXR(initResult = xrGetSystem(vr_engine.appState.Instance, &systemGetInfo, &systemId));
if (initResult != XR_SUCCESS) {
ALOGE("Failed to get system.");
exit(1);
}
2022-07-08 14:44:20 +02:00
2022-07-24 14:25:04 +02:00
// Get the graphics requirements.
2022-11-06 14:37:56 +01:00
if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) {
PFN_xrGetVulkanGraphicsRequirementsKHR pfnGetVulkanGraphicsRequirementsKHR = NULL;
OXR(xrGetInstanceProcAddr(
vr_engine.appState.Instance,
"xrGetVulkanGraphicsRequirementsKHR",
(PFN_xrVoidFunction*)(&pfnGetVulkanGraphicsRequirementsKHR)));
2022-07-08 14:44:20 +02:00
XrGraphicsRequirementsVulkanKHR graphicsRequirements = {};
graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR;
OXR(pfnGetVulkanGraphicsRequirementsKHR(vr_engine.appState.Instance, systemId, &graphicsRequirements));
} else {
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
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));
#endif
}
2022-07-08 14:44:20 +02:00
#ifdef ANDROID
2022-07-24 14:25:04 +02:00
vr_engine.appState.MainThreadTid = gettid();
#endif
2022-07-24 14:25:04 +02:00
vr_engine.appState.SystemId = systemId;
vr_initialized = 1;
2022-07-08 14:44:20 +02:00
}
2022-07-23 13:14:53 +02:00
void VR_Destroy( engine_t* engine ) {
2022-07-24 14:25:04 +02:00
if (engine == &vr_engine) {
xrDestroyInstance(engine->appState.Instance);
ovrApp_Destroy(&engine->appState);
}
2022-07-08 14:44:20 +02:00
}
2022-09-14 19:53:55 +02:00
void VR_EnterVR( engine_t* engine, XrGraphicsBindingVulkanKHR* graphicsBindingVulkan ) {
2022-07-08 14:44:20 +02:00
2022-07-24 14:25:04 +02:00
if (engine->appState.Session) {
ALOGE("VR_EnterVR called with existing session");
return;
}
2022-07-08 14:44:20 +02:00
2022-07-24 14:25:04 +02:00
// Create the OpenXR Session.
XrSessionCreateInfo sessionCreateInfo = {};
2022-11-04 14:22:42 +01:00
#ifdef ANDROID
XrGraphicsBindingOpenGLESAndroidKHR graphicsBindingGL = {};
#elif XR_USE_GRAPHICS_API_OPENGL
2022-11-04 14:22:42 +01:00
XrGraphicsBindingOpenGLWin32KHR graphicsBindingGL = {};
#endif
2022-07-24 14:25:04 +02:00
memset(&sessionCreateInfo, 0, sizeof(sessionCreateInfo));
2022-11-06 14:37:56 +01:00
if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) {
2022-09-14 19:53:55 +02:00
sessionCreateInfo.next = graphicsBindingVulkan;
} else {
2022-11-04 14:22:42 +01:00
#ifdef ANDROID
graphicsBindingGL.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR;
graphicsBindingGL.next = NULL;
graphicsBindingGL.display = eglGetCurrentDisplay();
graphicsBindingGL.config = NULL;
2022-11-04 14:22:42 +01:00
graphicsBindingGL.context = eglGetCurrentContext();
sessionCreateInfo.next = &graphicsBindingGL;
2022-11-04 14:22:42 +01:00
#else
//TODO:PCVR definition
#endif
2022-09-14 19:53:55 +02:00
}
2022-07-24 14:25:04 +02:00
sessionCreateInfo.type = XR_TYPE_SESSION_CREATE_INFO;
sessionCreateInfo.createFlags = 0;
sessionCreateInfo.systemId = engine->appState.SystemId;
2022-07-08 14:44:20 +02:00
2022-07-24 14:25:04 +02:00
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);
}
2022-07-08 14:44:20 +02:00
2022-07-24 14:25:04 +02:00
// 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));
2022-07-08 14:44:20 +02:00
}
void VR_LeaveVR( engine_t* engine ) {
2022-07-24 14:25:04 +02:00
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 = XR_NULL_HANDLE;
2022-07-24 14:25:04 +02:00
}
2022-07-08 14:44:20 +02:00
}
engine_t* VR_GetEngine( void ) {
return &vr_engine;
}
2022-11-06 14:37:56 +01:00
bool VR_GetPlatformFlag(VRPlatformFlag flag) {
2022-11-04 14:22:42 +01:00
return vr_platform[flag];
}
void VR_SetPlatformFLag(VRPlatformFlag flag, bool value) {
vr_platform[flag] = value;
}