Skip to content

Commit

Permalink
Add WinlatorXR by lvonasek (https://github.com/lvonasek)
Browse files Browse the repository at this point in the history
  • Loading branch information
brunodev85 committed Mar 28, 2024
1 parent 8f79ebc commit 3af161c
Show file tree
Hide file tree
Showing 21 changed files with 2,584 additions and 8 deletions.
3 changes: 3 additions & 0 deletions app/.gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "src/main/cpp/OpenXR-SDK"]
path = src/main/cpp/OpenXR-SDK
url = https://github.com/KhronosGroup/OpenXR-SDK.git
24 changes: 24 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<uses-feature
android:name="android.hardware.vr.headtracking"
android:required="false" />
<uses-feature
android:name="com.oculus.feature.PASSTHROUGH"
android:required="false" />
<uses-feature
android:name="oculus.software.overlay_keyboard"
android:required="false" />

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Expand Down Expand Up @@ -37,6 +46,21 @@
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|density|navigation"
android:screenOrientation="sensorLandscape" />

<activity
android:name="com.winlator.XrActivity"
android:configChanges="density|orientation|screenSize|keyboard|keyboardHidden|uiMode"
android:exported="true"
android:launchMode="singleTask"
android:resizeableActivity="false"
android:screenOrientation="landscape"
android:process=":vr_process"
android:theme="@style/AppThemeFullscreen">
<intent-filter>
<category android:name="com.oculus.intent.category.VR" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity android:name="com.winlator.ControlsEditorActivity"
android:exported="false"
android:theme="@style/AppThemeFullscreen"
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
cmake_minimum_required(VERSION 3.22.1)

Project(Winlator)

set(CMAKE_C_FLAGS "-O2 -Wno-unused-function -Wimplicit-function-declaration")

add_subdirectory(proot)
add_subdirectory(virglrenderer)
add_subdirectory(OpenXR-SDK)

add_library(winlator SHARED
xr/engine.c
xr/framebuffer.c
xr/input.c
xr/main.c
xr/math.c
xr/renderer.c
drawable.c
gpu_image.c
sysvshared_memory.c
Expand All @@ -15,6 +24,7 @@ target_link_libraries(winlator
log
android
jnigraphics
openxr_loader
EGL
GLESv2
GLESv3)
1 change: 1 addition & 0 deletions app/src/main/cpp/OpenXR-SDK
Submodule OpenXR-SDK added at 288d3a
207 changes: 207 additions & 0 deletions app/src/main/cpp/xr/engine.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
#include "engine.h"

#include <stdlib.h>
#include <string.h>
#include <unistd.h>

void XrEngineInit(struct XrEngine* engine, void* system, const char* name, int version)
{
if (engine->Initialized)
return;
memset(engine, 0, sizeof(engine));

#ifdef ANDROID
PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR;
xrGetInstanceProcAddr(XR_NULL_HANDLE, "xrInitializeLoaderKHR",
(PFN_xrVoidFunction*)&xrInitializeLoaderKHR);
if (xrInitializeLoaderKHR != NULL)
{
xrJava* java = (xrJava*)system;
XrLoaderInitInfoAndroidKHR loader_info;
memset(&loader_info, 0, sizeof(loader_info));
loader_info.type = XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR;
loader_info.next = NULL;
loader_info.applicationVM = java->vm;
loader_info.applicationContext = java->activity;
xrInitializeLoaderKHR((XrLoaderInitInfoBaseHeaderKHR*)&loader_info);
}
#endif

int count = 0;
const char* extensions[32];
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
extensions[count++] = XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME;
#endif
#ifdef ANDROID
if (engine->PlatformFlag[PLATFORM_EXTENSION_INSTANCE])
{
extensions[count++] = XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME;
}
if (engine->PlatformFlag[PLATFORM_EXTENSION_PASSTHROUGH])
{
extensions[count++] = XR_FB_PASSTHROUGH_EXTENSION_NAME;
}
if (engine->PlatformFlag[PLATFORM_EXTENSION_PERFORMANCE])
{
extensions[count++] = XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME;
extensions[count++] = XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME;
}
#endif

// Create the OpenXR instance.
XrApplicationInfo app_info;
memset(&app_info, 0, sizeof(app_info));
strcpy(app_info.applicationName, name);
strcpy(app_info.engineName, name);
app_info.applicationVersion = version;
app_info.engineVersion = version;
app_info.apiVersion = XR_CURRENT_API_VERSION;

XrInstanceCreateInfo instance_info;
memset(&instance_info, 0, sizeof(instance_info));
instance_info.type = XR_TYPE_INSTANCE_CREATE_INFO;
instance_info.next = NULL;
instance_info.createFlags = 0;
instance_info.applicationInfo = app_info;
instance_info.enabledApiLayerCount = 0;
instance_info.enabledApiLayerNames = NULL;
instance_info.enabledExtensionCount = count;
instance_info.enabledExtensionNames = extensions;

#ifdef ANDROID
XrInstanceCreateInfoAndroidKHR instance_info_android = {XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR};
if (engine->PlatformFlag[PLATFORM_EXTENSION_INSTANCE])
{
xrJava* java = (xrJava*)system;
instance_info_android.applicationVM = java->vm;
instance_info_android.applicationActivity = java->activity;
instance_info.next = (XrBaseInStructure*)&instance_info_android;
}
#endif

XrResult result;
OXR(result = xrCreateInstance(&instance_info, &engine->Instance));
if (result != XR_SUCCESS)
{
ALOGE("Failed to create XR instance: %d", (int)result);
exit(1);
}

XrInstanceProperties instance_properties;
instance_properties.type = XR_TYPE_INSTANCE_PROPERTIES;
instance_properties.next = NULL;
OXR(xrGetInstanceProperties(engine->Instance, &instance_properties));
ALOGV("Runtime %s: Version : %d.%d.%d", instance_properties.runtimeName,
XR_VERSION_MAJOR(instance_properties.runtimeVersion),
XR_VERSION_MINOR(instance_properties.runtimeVersion),
XR_VERSION_PATCH(instance_properties.runtimeVersion));

XrSystemGetInfo system_info;
memset(&system_info, 0, sizeof(system_info));
system_info.type = XR_TYPE_SYSTEM_GET_INFO;
system_info.next = NULL;
system_info.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;

OXR(result = xrGetSystem(engine->Instance, &system_info, &engine->SystemId));
if (result != XR_SUCCESS)
{
ALOGE("Failed to get system");
exit(1);
}

// Get the graphics requirements.
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
PFN_xrGetOpenGLESGraphicsRequirementsKHR pfnGetOpenGLESGraphicsRequirementsKHR = NULL;
OXR(xrGetInstanceProcAddr(engine->Instance, "xrGetOpenGLESGraphicsRequirementsKHR",
(PFN_xrVoidFunction*)(&pfnGetOpenGLESGraphicsRequirementsKHR)));

XrGraphicsRequirementsOpenGLESKHR graphics_requirements = {};
graphics_requirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR;
OXR(pfnGetOpenGLESGraphicsRequirementsKHR(engine->Instance, engine->SystemId, &graphics_requirements));
#endif

#ifdef ANDROID
engine->MainThreadId = gettid();
#endif
engine->Initialized = true;
}

void XrEngineDestroy(struct XrEngine* engine)
{
if (engine->Initialized)
{
xrDestroyInstance(engine->Instance);
engine->Initialized = false;
}
}

void XrEngineEnter(struct XrEngine* engine)
{
if (engine->Session)
{
ALOGE("EnterXR called with existing session");
return;
}

// Create the OpenXR Session.
XrSessionCreateInfo session_info;
memset(&session_info, 0, sizeof(session_info));
#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
XrGraphicsBindingOpenGLESAndroidKHR graphics_binding_gl = {};
graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR;
graphics_binding_gl.next = NULL;
graphics_binding_gl.display = eglGetCurrentDisplay();
graphics_binding_gl.config = NULL;
graphics_binding_gl.context = eglGetCurrentContext();
session_info.next = &graphics_binding_gl;
#endif
session_info.type = XR_TYPE_SESSION_CREATE_INFO;
session_info.createFlags = 0;
session_info.systemId = engine->SystemId;

XrResult result;
OXR(result = xrCreateSession(engine->Instance, &session_info, &engine->Session));
if (result != XR_SUCCESS)
{
ALOGE("Failed to create XR session: %d", (int)result);
exit(1);
}

// Create a space to the first path
XrReferenceSpaceCreateInfo space_info = {};
space_info.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
space_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW;
space_info.poseInReferenceSpace.orientation.w = 1.0f;
OXR(xrCreateReferenceSpace(engine->Session, &space_info, &engine->HeadSpace));
}

void XrEngineLeave(struct XrEngine* engine)
{
if (engine->Session)
{
OXR(xrDestroySpace(engine->HeadSpace));
// StageSpace is optional.
if (engine->StageSpace != XR_NULL_HANDLE)
{
OXR(xrDestroySpace(engine->StageSpace));
}
OXR(xrDestroySpace(engine->FakeSpace));
engine->CurrentSpace = XR_NULL_HANDLE;
OXR(xrDestroySession(engine->Session));
engine->Session = XR_NULL_HANDLE;
}
}

void XrEngineWaitForFrame(struct XrEngine* engine)
{
XrFrameWaitInfo wait_frame_info = {};
wait_frame_info.type = XR_TYPE_FRAME_WAIT_INFO;
wait_frame_info.next = NULL;

XrFrameState frame_state = {};
frame_state.type = XR_TYPE_FRAME_STATE;
frame_state.next = NULL;

OXR(xrWaitFrame(engine->Session, &wait_frame_info, &frame_state));
engine->PredictedDisplayTime = frame_state.predictedDisplayTime;
}
99 changes: 99 additions & 0 deletions app/src/main/cpp/xr/engine.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#pragma once

#include <stdbool.h>

//#define _DEBUG

#ifndef ANDROID
#define ANDROID 1
#endif

#if defined(_DEBUG)
void GLCheckErrors(const char* file, int line);
void OXRCheckErrors(XrResult result, const char* file, int line);

#define GL(func) func; GLCheckErrors(__FILE__ , __LINE__);
#define OXR(func) OXRCheckErrors(func, __FILE__ , __LINE__);
#else
#define GL(func) func;
#define OXR(func) func;
#endif

#ifdef ANDROID
#include <android/log.h>
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, "OpenXR", __VA_ARGS__);
#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "OpenXR", __VA_ARGS__);

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <jni.h>
#define XR_USE_PLATFORM_ANDROID 1
#define XR_USE_GRAPHICS_API_OPENGL_ES 1
#else
#include <cstdio>
#define ALOGE(...) printf(__VA_ARGS__)
#define ALOGV(...) printf(__VA_ARGS__)
#endif

#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>

enum
{
XrMaxLayerCount = 2
};
enum
{
XrMaxNumEyes = 2
};

enum XrPlatformFlag
{
PLATFORM_CONTROLLER_PICO,
PLATFORM_CONTROLLER_QUEST,
PLATFORM_EXTENSION_INSTANCE,
PLATFORM_EXTENSION_PASSTHROUGH,
PLATFORM_EXTENSION_PERFORMANCE,
PLATFORM_TRACKING_FLOOR,
PLATFORM_MAX
};

typedef union
{
XrCompositionLayerProjection projection;
XrCompositionLayerQuad quad;
} XrCompositorLayer;

#ifdef ANDROID
typedef struct
{
jobject activity;
JNIEnv* env;
JavaVM* vm;
} xrJava;
#endif

struct XrEngine {
XrInstance Instance;
XrSession Session;
XrSystemId SystemId;

XrSpace CurrentSpace;
XrSpace FakeSpace;
XrSpace HeadSpace;
XrSpace StageSpace;

XrTime PredictedDisplayTime;

int MainThreadId;
int RenderThreadId;

bool PlatformFlag[PLATFORM_MAX];
bool Initialized;
};

void XrEngineInit(struct XrEngine* engine, void* system, const char* name, int version);
void XrEngineDestroy(struct XrEngine* engine);
void XrEngineEnter(struct XrEngine* engine);
void XrEngineLeave(struct XrEngine* engine);
void XrEngineWaitForFrame(struct XrEngine* engine);
Loading

0 comments on commit 3af161c

Please sign in to comment.