mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +00:00
OpenXR - VR mode initialization added
This commit is contained in:
parent
dc977a2eed
commit
9893e5c4ab
@ -118,8 +118,9 @@ add_definitions(-DASSETS_DIR="${CMAKE_INSTALL_FULL_DATADIR}/ppsspp/assets/")
|
||||
|
||||
if(OPENXR)
|
||||
add_definitions(-DOPENXR)
|
||||
include_directories(ext/openxr vr)
|
||||
link_directories(quest/libs/arm64-v8a)
|
||||
add_library(openxr SHARED IMPORTED)
|
||||
include_directories(ext/openxr)
|
||||
set_property(TARGET openxr PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/ext/openxr/libs/arm64-v8a/libopenxr_loader.so")
|
||||
message("OpenXR enabled")
|
||||
endif()
|
||||
|
||||
@ -1066,9 +1067,12 @@ if(ANDROID)
|
||||
|
||||
if (OPENXR)
|
||||
set(nativeExtra ${nativeExtra}
|
||||
VR/VRFramebuffer.c
|
||||
VR/VRBase.cpp
|
||||
VR/VRBase.h
|
||||
VR/VRFramebuffer.cpp
|
||||
VR/VRFramebuffer.h
|
||||
)
|
||||
set(nativeExtraLibs ${nativeExtraLibs} openxr)
|
||||
endif()
|
||||
# No target
|
||||
elseif(IOS)
|
||||
|
@ -843,7 +843,11 @@ static ConfigSetting graphicsSettings[] = {
|
||||
ConfigSetting("CardboardXShift", &g_Config.iCardboardXShift, 0, true, true),
|
||||
ConfigSetting("CardboardYShift", &g_Config.iCardboardYShift, 0, true, true),
|
||||
ConfigSetting("ShowFPSCounter", &g_Config.iShowFPSCounter, 0, true, true),
|
||||
#ifdef OPENXR
|
||||
g_Config.iGPUBackend = (int)GPUBackend::OPENGL,
|
||||
#else
|
||||
ReportedConfigSetting("GraphicsBackend", &g_Config.iGPUBackend, &DefaultGPUBackend, &GPUBackendTranslator::To, &GPUBackendTranslator::From, true, false),
|
||||
#endif
|
||||
ConfigSetting("FailedGraphicsBackends", &g_Config.sFailedGPUBackends, ""),
|
||||
ConfigSetting("DisabledGraphicsBackends", &g_Config.sDisabledGPUBackends, ""),
|
||||
ConfigSetting("VulkanDevice", &g_Config.sVulkanDevice, "", true, false),
|
||||
|
@ -96,6 +96,10 @@ using namespace std::placeholders;
|
||||
static AVIDump avi;
|
||||
#endif
|
||||
|
||||
#ifdef OPENXR
|
||||
#include "VR/VRBase.h"
|
||||
#endif
|
||||
|
||||
// TODO: Ugly!
|
||||
static bool frameStep_;
|
||||
static int lastNumFlips;
|
||||
@ -189,6 +193,10 @@ EmuScreen::EmuScreen(const Path &filename)
|
||||
// Usually, we don't want focus movement enabled on this screen, so disable on start.
|
||||
// Only if you open chat or dev tools do we want it to start working.
|
||||
UI::EnableFocusMovement(false);
|
||||
|
||||
#ifdef OPENXR
|
||||
VR_EnterVR(VR_GetEngine());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool EmuScreen::bootAllowStorage(const Path &filename) {
|
||||
|
176
VR/VRBase.cpp
Normal file
176
VR/VRBase.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
#include "VRBase.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static engine_t vr_engine;
|
||||
int vr_initialized = 0;
|
||||
|
||||
const char* const requiredExtensionNames[] = {
|
||||
XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME,
|
||||
XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME,
|
||||
XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME};
|
||||
const uint32_t numRequiredExtensions =
|
||||
sizeof(requiredExtensionNames) / sizeof(requiredExtensionNames[0]);
|
||||
|
||||
void VR_Init( ovrJava java )
|
||||
{
|
||||
if (vr_initialized)
|
||||
return;
|
||||
|
||||
ovrApp_Clear(&vr_engine.appState);
|
||||
|
||||
// Create the EGL Context
|
||||
ovrEgl_CreateContext(&vr_engine.appState.Egl, NULL);
|
||||
|
||||
XrInstanceCreateInfoAndroidKHR instanceCreateInfoAndroid = {XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR};
|
||||
instanceCreateInfoAndroid.applicationVM = java.Vm;
|
||||
instanceCreateInfoAndroid.applicationActivity = java.ActivityObject;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// Create the OpenXR instance.
|
||||
XrApplicationInfo appInfo;
|
||||
memset(&appInfo, 0, sizeof(appInfo));
|
||||
strcpy(appInfo.applicationName, "PPSSPP");
|
||||
appInfo.applicationVersion = 0;
|
||||
strcpy(appInfo.engineName, "PPSSPP");
|
||||
appInfo.engineVersion = 0;
|
||||
appInfo.apiVersion = XR_CURRENT_API_VERSION;
|
||||
|
||||
XrInstanceCreateInfo instanceCreateInfo;
|
||||
memset(&instanceCreateInfo, 0, sizeof(instanceCreateInfo));
|
||||
instanceCreateInfo.type = XR_TYPE_INSTANCE_CREATE_INFO;
|
||||
instanceCreateInfo.next = (XrBaseInStructure*)&instanceCreateInfoAndroid;
|
||||
instanceCreateInfo.createFlags = 0;
|
||||
instanceCreateInfo.applicationInfo = appInfo;
|
||||
instanceCreateInfo.enabledApiLayerCount = 0;
|
||||
instanceCreateInfo.enabledApiLayerNames = NULL;
|
||||
instanceCreateInfo.enabledExtensionCount = numRequiredExtensions;
|
||||
instanceCreateInfo.enabledExtensionNames = requiredExtensionNames;
|
||||
|
||||
XrResult initResult;
|
||||
OXR(initResult = xrCreateInstance(&instanceCreateInfo, &vr_engine.appState.Instance));
|
||||
if (initResult != XR_SUCCESS) {
|
||||
ALOGE("Failed to create XR instance: %d.", initResult);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
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.
|
||||
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_initialized = 1;
|
||||
}
|
||||
|
||||
void VR_Destroy( engine_t* engine )
|
||||
{
|
||||
if (engine == &vr_engine) {
|
||||
xrDestroyInstance(engine->appState.Instance);
|
||||
ovrEgl_DestroyContext(&engine->appState.Egl);
|
||||
ovrApp_Destroy(&engine->appState);
|
||||
}
|
||||
}
|
||||
|
||||
void VR_EnterVR( engine_t* engine ) {
|
||||
|
||||
if (engine->appState.Session) {
|
||||
ALOGE("VR_EnterVR called with existing session");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the OpenXR Session.
|
||||
XrGraphicsBindingOpenGLESAndroidKHR graphicsBindingAndroidGLES = {};
|
||||
graphicsBindingAndroidGLES.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR;
|
||||
graphicsBindingAndroidGLES.next = NULL;
|
||||
graphicsBindingAndroidGLES.display = engine->appState.Egl.Display;
|
||||
graphicsBindingAndroidGLES.config = engine->appState.Egl.Config;
|
||||
graphicsBindingAndroidGLES.context = engine->appState.Egl.Context;
|
||||
|
||||
XrSessionCreateInfo sessionCreateInfo = {};
|
||||
memset(&sessionCreateInfo, 0, sizeof(sessionCreateInfo));
|
||||
sessionCreateInfo.type = XR_TYPE_SESSION_CREATE_INFO;
|
||||
sessionCreateInfo.next = &graphicsBindingAndroidGLES;
|
||||
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);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
13
VR/VRBase.h
Normal file
13
VR/VRBase.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef __VR_BASE
|
||||
#define __VR_BASE
|
||||
|
||||
#include "VRFramebuffer.h"
|
||||
|
||||
void VR_Init( ovrJava java );
|
||||
void VR_Destroy( engine_t* engine );
|
||||
void VR_EnterVR( engine_t* engine );
|
||||
void VR_LeaveVR( engine_t* engine );
|
||||
|
||||
engine_t* VR_GetEngine( void );
|
||||
|
||||
#endif
|
@ -17,6 +17,8 @@ Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rig
|
||||
#include <pthread.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <assert.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <GLES3/gl3ext.h>
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
@ -420,9 +422,9 @@ void ovrApp_HandleSessionStateChanges(ovrApp* app, XrSessionState state) {
|
||||
}
|
||||
}
|
||||
|
||||
GLboolean ovrApp_HandleXrEvents(ovrApp* app) {
|
||||
int ovrApp_HandleXrEvents(ovrApp* app) {
|
||||
XrEventDataBuffer eventDataBuffer = {};
|
||||
GLboolean recenter = GL_FALSE;
|
||||
int recenter = 0;
|
||||
|
||||
// Poll for events
|
||||
for (;;) {
|
||||
@ -467,7 +469,7 @@ GLboolean ovrApp_HandleXrEvents(ovrApp* app) {
|
||||
ref_space_change_event->referenceSpaceType,
|
||||
(void*)ref_space_change_event->session,
|
||||
FromXrTime(ref_space_change_event->changeTime));
|
||||
recenter = GL_TRUE;
|
||||
recenter = 1;
|
||||
} break;
|
||||
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: {
|
||||
const XrEventDataSessionStateChanged* session_state_changed_event =
|
@ -6,8 +6,6 @@
|
||||
#define XR_USE_PLATFORM_ANDROID 1
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <GLES3/gl3ext.h>
|
||||
#include <jni.h>
|
||||
#include <math.h>
|
||||
#include <openxr.h>
|
||||
@ -58,8 +56,8 @@ typedef struct {
|
||||
uint32_t TextureSwapChainIndex;
|
||||
ovrSwapChain ColorSwapChain;
|
||||
XrSwapchainImageOpenGLESKHR* ColorSwapChainImage;
|
||||
GLuint* DepthBuffers;
|
||||
GLuint* FrameBuffers;
|
||||
unsigned int* DepthBuffers;
|
||||
unsigned int* FrameBuffers;
|
||||
} ovrFramebuffer;
|
||||
|
||||
typedef struct {
|
||||
@ -67,13 +65,13 @@ typedef struct {
|
||||
} ovrRenderer;
|
||||
|
||||
typedef struct {
|
||||
GLboolean Active;
|
||||
int Active;
|
||||
XrPosef Pose;
|
||||
} ovrTrackedController;
|
||||
|
||||
typedef struct {
|
||||
ovrEgl Egl;
|
||||
GLboolean Focused;
|
||||
int Focused;
|
||||
|
||||
XrInstance Instance;
|
||||
XrSession Session;
|
||||
@ -84,7 +82,7 @@ typedef struct {
|
||||
XrSpace StageSpace;
|
||||
XrSpace FakeStageSpace;
|
||||
XrSpace CurrentSpace;
|
||||
GLboolean SessionActive;
|
||||
int SessionActive;
|
||||
|
||||
int SwapInterval;
|
||||
// These threads will be marked as performance threads.
|
||||
@ -93,7 +91,7 @@ typedef struct {
|
||||
ovrCompositorLayer_Union Layers[ovrMaxLayerCount];
|
||||
int LayerCount;
|
||||
|
||||
GLboolean TouchPadDownLastFrame;
|
||||
int TouchPadDownLastFrame;
|
||||
ovrRenderer Renderer;
|
||||
ovrTrackedController TrackedController[2];
|
||||
} ovrApp;
|
||||
@ -138,7 +136,7 @@ typedef struct {
|
||||
|
||||
void ovrApp_Clear(ovrApp* app);
|
||||
void ovrApp_Destroy(ovrApp* app);
|
||||
GLboolean ovrApp_HandleXrEvents(ovrApp* app);
|
||||
int ovrApp_HandleXrEvents(ovrApp* app);
|
||||
|
||||
void ovrEgl_CreateContext(ovrEgl* egl, const ovrEgl* shareEgl);
|
||||
void ovrEgl_DestroyContext(ovrEgl* egl);
|
||||
|
@ -93,6 +93,10 @@ struct JNIEnv {};
|
||||
#include "Common/Log.h"
|
||||
#include "UI/GameInfoCache.h"
|
||||
|
||||
#ifdef OPENXR
|
||||
#include "VR/VRBase.h"
|
||||
#endif
|
||||
|
||||
#include "app-android.h"
|
||||
|
||||
bool useCPUThread = true;
|
||||
@ -753,6 +757,13 @@ retry:
|
||||
INFO_LOG(SYSTEM, "NativeApp.init() - launching emu thread");
|
||||
EmuThreadStart();
|
||||
}
|
||||
|
||||
#ifdef OPENXR
|
||||
ovrJava java;
|
||||
java.Vm = gJvm;
|
||||
java.ActivityObject = nativeActivity;
|
||||
VR_Init(java);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_audioInit(JNIEnv *, jclass) {
|
||||
|
@ -10,6 +10,7 @@
|
||||
<!-- Also note that we are overriding these values anyway from gradle. -->
|
||||
|
||||
<uses-feature android:glEsVersion="0x00020000" />
|
||||
<uses-feature android:name="android.hardware.vr.headtracking" android:version="1" android:required="true" />
|
||||
<uses-feature android:name="android.hardware.screen.landscape" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
||||
<uses-feature android:name="android.software.leanback" android:required="false" />
|
||||
@ -50,7 +51,10 @@
|
||||
android:banner="@drawable/tv_banner"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:preserveLegacyExternalStorage="true">
|
||||
<meta-data android:name="android.max_aspect" android:value="2.4" />
|
||||
|
||||
<meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
|
||||
<meta-data android:name="com.oculus.supportedDevices" android:value="quest|quest2"/>
|
||||
|
||||
<activity
|
||||
android:name=".PpssppActivity"
|
||||
android:configChanges="locale|keyboard|keyboardHidden|navigation|uiMode"
|
||||
|
@ -100,7 +100,6 @@ android {
|
||||
aidl.srcDirs = ['../android/src']
|
||||
resources.srcDirs = ['../android/src']
|
||||
assets.srcDirs = ['../assets']
|
||||
jniLibs.srcDirs = ['libs']
|
||||
}
|
||||
gold {
|
||||
res.srcDirs = ['../android/gold/res']
|
||||
|
Loading…
Reference in New Issue
Block a user