mirror of
https://github.com/DrBeef/ioq3quest.git
synced 2024-11-25 13:31:10 +00:00
OpenXR tracking added init, first working rendering
This commit is contained in:
parent
8431b1aa83
commit
0de4a0d196
4 changed files with 701 additions and 451 deletions
|
@ -6,6 +6,7 @@
|
||||||
//#if __ANDROID__
|
//#if __ANDROID__
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
static engine_t vr_engine;
|
static engine_t vr_engine;
|
||||||
|
|
||||||
|
@ -13,15 +14,9 @@ const char* const requiredExtensionNames[] = {
|
||||||
XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME,
|
XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME,
|
||||||
XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME,
|
XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME,
|
||||||
XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME,
|
XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME,
|
||||||
XR_KHR_COMPOSITION_LAYER_CUBE_EXTENSION_NAME,
|
|
||||||
XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME,
|
|
||||||
XR_KHR_COMPOSITION_LAYER_EQUIRECT2_EXTENSION_NAME,
|
|
||||||
XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME,
|
XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME,
|
||||||
XR_FB_COLOR_SPACE_EXTENSION_NAME,
|
|
||||||
XR_FB_SWAPCHAIN_UPDATE_STATE_EXTENSION_NAME,
|
XR_FB_SWAPCHAIN_UPDATE_STATE_EXTENSION_NAME,
|
||||||
XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME,
|
XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME};
|
||||||
XR_FB_FOVEATION_EXTENSION_NAME,
|
|
||||||
XR_FB_FOVEATION_CONFIGURATION_EXTENSION_NAME};
|
|
||||||
const uint32_t numRequiredExtensions =
|
const uint32_t numRequiredExtensions =
|
||||||
sizeof(requiredExtensionNames) / sizeof(requiredExtensionNames[0]);
|
sizeof(requiredExtensionNames) / sizeof(requiredExtensionNames[0]);
|
||||||
|
|
||||||
|
@ -50,7 +45,7 @@ cvar_t *vr_goreLevel = NULL;
|
||||||
|
|
||||||
engine_t* VR_Init( ovrJava java )
|
engine_t* VR_Init( ovrJava java )
|
||||||
{
|
{
|
||||||
memset(&vr_engine, 0, sizeof(vr_engine));
|
ovrApp_Clear(&vr_engine.appState);
|
||||||
|
|
||||||
PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR;
|
PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR;
|
||||||
xrGetInstanceProcAddr(
|
xrGetInstanceProcAddr(
|
||||||
|
@ -84,21 +79,52 @@ engine_t* VR_Init( ovrJava java )
|
||||||
instanceCreateInfo.enabledApiLayerNames = NULL;
|
instanceCreateInfo.enabledApiLayerNames = NULL;
|
||||||
instanceCreateInfo.enabledExtensionCount = numRequiredExtensions;
|
instanceCreateInfo.enabledExtensionCount = numRequiredExtensions;
|
||||||
instanceCreateInfo.enabledExtensionNames = requiredExtensionNames;
|
instanceCreateInfo.enabledExtensionNames = requiredExtensionNames;
|
||||||
if (xrCreateInstance(&instanceCreateInfo, &vr_engine.instance) != XR_SUCCESS) {
|
|
||||||
Com_Printf("xrCreateInstance failed");
|
XrResult initResult;
|
||||||
|
OXR(initResult = xrCreateInstance(&instanceCreateInfo, &vr_engine.appState.Instance));
|
||||||
|
if (initResult != XR_SUCCESS) {
|
||||||
|
ALOGE("Failed to create XR instance: %d.", initResult);
|
||||||
exit(1);
|
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;
|
XrSystemGetInfo systemGetInfo;
|
||||||
memset(&systemGetInfo, 0, sizeof(systemGetInfo));
|
memset(&systemGetInfo, 0, sizeof(systemGetInfo));
|
||||||
systemGetInfo.type = XR_TYPE_SYSTEM_GET_INFO;
|
systemGetInfo.type = XR_TYPE_SYSTEM_GET_INFO;
|
||||||
systemGetInfo.next = NULL;
|
systemGetInfo.next = NULL;
|
||||||
systemGetInfo.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
|
systemGetInfo.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
|
||||||
if (xrGetSystem(vr_engine.instance, &systemGetInfo, &vr_engine.systemId) != XR_SUCCESS) {
|
|
||||||
Com_Printf("xrGetSystem failed");
|
XrSystemId systemId;
|
||||||
|
OXR(initResult = xrGetSystem(vr_engine.appState.Instance, &systemGetInfo, &systemId));
|
||||||
|
if (initResult != XR_SUCCESS) {
|
||||||
|
ALOGE("Failed to get system.");
|
||||||
exit(1);
|
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_engine.java = java;
|
||||||
return &vr_engine;
|
return &vr_engine;
|
||||||
}
|
}
|
||||||
|
@ -224,27 +250,18 @@ void VR_InitCvars( void )
|
||||||
void VR_Destroy( engine_t* engine )
|
void VR_Destroy( engine_t* engine )
|
||||||
{
|
{
|
||||||
if (engine == &vr_engine) {
|
if (engine == &vr_engine) {
|
||||||
xrDestroyInstance(engine->instance);
|
xrDestroyInstance(engine->appState.Instance);
|
||||||
|
ovrApp_Destroy(&engine->appState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VR_EnterVR( engine_t* engine, ovrJava java ) {
|
void VR_EnterVR( engine_t* engine, ovrJava java ) {
|
||||||
|
|
||||||
if (engine->session) {
|
if (engine->appState.Session) {
|
||||||
Com_Printf("VR_EnterVR called with existing session");
|
Com_Printf("VR_EnterVR called with existing session");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the graphics requirements.
|
|
||||||
PFN_xrGetOpenGLESGraphicsRequirementsKHR pfnGetOpenGLESGraphicsRequirementsKHR = NULL;
|
|
||||||
xrGetInstanceProcAddr(
|
|
||||||
engine->instance,
|
|
||||||
"xrGetOpenGLESGraphicsRequirementsKHR",
|
|
||||||
(PFN_xrVoidFunction*)(&pfnGetOpenGLESGraphicsRequirementsKHR));
|
|
||||||
XrGraphicsRequirementsOpenGLESKHR graphicsRequirements = {};
|
|
||||||
graphicsRequirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR;
|
|
||||||
pfnGetOpenGLESGraphicsRequirementsKHR(engine->instance, engine->systemId, &graphicsRequirements);
|
|
||||||
|
|
||||||
// Create the OpenXR Session.
|
// Create the OpenXR Session.
|
||||||
XrGraphicsBindingOpenGLESAndroidKHR graphicsBindingAndroidGLES = {};
|
XrGraphicsBindingOpenGLESAndroidKHR graphicsBindingAndroidGLES = {};
|
||||||
graphicsBindingAndroidGLES.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR;
|
graphicsBindingAndroidGLES.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR;
|
||||||
|
@ -258,17 +275,29 @@ void VR_EnterVR( engine_t* engine, ovrJava java ) {
|
||||||
sessionCreateInfo.type = XR_TYPE_SESSION_CREATE_INFO;
|
sessionCreateInfo.type = XR_TYPE_SESSION_CREATE_INFO;
|
||||||
sessionCreateInfo.next = &graphicsBindingAndroidGLES;
|
sessionCreateInfo.next = &graphicsBindingAndroidGLES;
|
||||||
sessionCreateInfo.createFlags = 0;
|
sessionCreateInfo.createFlags = 0;
|
||||||
sessionCreateInfo.systemId = engine->systemId;
|
sessionCreateInfo.systemId = engine->appState.SystemId;
|
||||||
if (xrCreateSession(engine->instance, &sessionCreateInfo, &engine->session) != XR_SUCCESS) {
|
|
||||||
Com_Printf("xrCreateSession failed");
|
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);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VR_LeaveVR( engine_t* engine ) {
|
void VR_LeaveVR( engine_t* engine ) {
|
||||||
if (engine->session) {
|
if (engine->appState.Session) {
|
||||||
xrDestroySession(engine->session);
|
OXR(xrDestroySpace(engine->appState.HeadSpace));
|
||||||
engine->session = NULL;
|
OXR(xrDestroySpace(engine->appState.LocalSpace));
|
||||||
|
// 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));
|
||||||
|
OXR(xrDestroyInstance(engine->appState.Instance));
|
||||||
|
engine->appState.Session = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,28 @@
|
||||||
#include <GLES3/gl32.h>
|
#include <GLES3/gl32.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SUPER_SAMPLE 1.15f
|
|
||||||
|
|
||||||
extern vr_clientinfo_t vr;
|
extern vr_clientinfo_t vr;
|
||||||
|
|
||||||
|
XrView* projections;
|
||||||
|
GLboolean stageSupported = GL_FALSE;
|
||||||
|
|
||||||
|
void VR_UpdateStageBounds(ovrApp* pappState) {
|
||||||
|
XrExtent2Df stageBounds = {};
|
||||||
|
|
||||||
|
XrResult result;
|
||||||
|
OXR(result = xrGetReferenceSpaceBoundsRect(
|
||||||
|
pappState->Session, XR_REFERENCE_SPACE_TYPE_STAGE, &stageBounds));
|
||||||
|
if (result != XR_SUCCESS) {
|
||||||
|
ALOGV("Stage bounds query failed: using small defaults");
|
||||||
|
stageBounds.width = 1.0f;
|
||||||
|
stageBounds.height = 1.0f;
|
||||||
|
|
||||||
|
pappState->CurrentSpace = pappState->FakeStageSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALOGV("Stage bounds: width = %f, depth %f", stageBounds.width, stageBounds.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void APIENTRY VR_GLDebugLog(GLenum source, GLenum type, GLuint id,
|
void APIENTRY VR_GLDebugLog(GLenum source, GLenum type, GLuint id,
|
||||||
GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
|
GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
|
||||||
|
@ -60,11 +78,81 @@ void VR_GetResolution(engine_t* engine, int *pWidth, int *pHeight)
|
||||||
|
|
||||||
if (engine)
|
if (engine)
|
||||||
{
|
{
|
||||||
|
// Enumerate the viewport configurations.
|
||||||
|
uint32_t viewportConfigTypeCount = 0;
|
||||||
|
OXR(xrEnumerateViewConfigurations(
|
||||||
|
engine->appState.Instance, engine->appState.SystemId, 0, &viewportConfigTypeCount, NULL));
|
||||||
|
|
||||||
|
XrViewConfigurationType* viewportConfigurationTypes =
|
||||||
|
(XrViewConfigurationType*)malloc(viewportConfigTypeCount * sizeof(XrViewConfigurationType));
|
||||||
|
|
||||||
|
OXR(xrEnumerateViewConfigurations(
|
||||||
|
engine->appState.Instance,
|
||||||
|
engine->appState.SystemId,
|
||||||
|
viewportConfigTypeCount,
|
||||||
|
&viewportConfigTypeCount,
|
||||||
|
viewportConfigurationTypes));
|
||||||
|
|
||||||
|
ALOGV("Available Viewport Configuration Types: %d", viewportConfigTypeCount);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < viewportConfigTypeCount; i++) {
|
||||||
|
const XrViewConfigurationType viewportConfigType = viewportConfigurationTypes[i];
|
||||||
|
|
||||||
|
ALOGV(
|
||||||
|
"Viewport configuration type %d : %s",
|
||||||
|
viewportConfigType,
|
||||||
|
viewportConfigType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO ? "Selected" : "");
|
||||||
|
|
||||||
|
XrViewConfigurationProperties viewportConfig;
|
||||||
|
viewportConfig.type = XR_TYPE_VIEW_CONFIGURATION_PROPERTIES;
|
||||||
|
OXR(xrGetViewConfigurationProperties(
|
||||||
|
engine->appState.Instance, engine->appState.SystemId, viewportConfigType, &viewportConfig));
|
||||||
|
ALOGV(
|
||||||
|
"FovMutable=%s ConfigurationType %d",
|
||||||
|
viewportConfig.fovMutable ? "true" : "false",
|
||||||
|
viewportConfig.viewConfigurationType);
|
||||||
|
|
||||||
|
uint32_t viewCount;
|
||||||
|
OXR(xrEnumerateViewConfigurationViews(
|
||||||
|
engine->appState.Instance, engine->appState.SystemId, viewportConfigType, 0, &viewCount, NULL));
|
||||||
|
|
||||||
|
if (viewCount > 0) {
|
||||||
|
XrViewConfigurationView* elements =
|
||||||
|
(XrViewConfigurationView*)malloc(viewCount * sizeof(XrViewConfigurationView));
|
||||||
|
|
||||||
|
for (uint32_t e = 0; e < viewCount; e++) {
|
||||||
|
elements[e].type = XR_TYPE_VIEW_CONFIGURATION_VIEW;
|
||||||
|
elements[e].next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
OXR(xrEnumerateViewConfigurationViews(
|
||||||
|
engine->appState.Instance,
|
||||||
|
engine->appState.SystemId,
|
||||||
|
viewportConfigType,
|
||||||
|
viewCount,
|
||||||
|
&viewCount,
|
||||||
|
elements));
|
||||||
|
|
||||||
|
// Cache the view config properties for the selected config type.
|
||||||
|
if (viewportConfigType == XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO) {
|
||||||
|
assert(viewCount == ovrMaxNumEyes);
|
||||||
|
for (uint32_t e = 0; e < viewCount; e++) {
|
||||||
|
engine->appState.ViewConfigurationView[e] = elements[e];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(elements);
|
||||||
|
} else {
|
||||||
|
ALOGE("Empty viewport configuration type: %d", viewCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(viewportConfigurationTypes);
|
||||||
|
|
||||||
|
*pWidth = width = engine->appState.ViewConfigurationView[0].recommendedImageRectWidth;
|
||||||
|
*pHeight = height = engine->appState.ViewConfigurationView[0].recommendedImageRectHeight;
|
||||||
//TODO:
|
//TODO:
|
||||||
/*
|
/*
|
||||||
*pWidth = width = vrapi_GetSystemPropertyInt(&engine->java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_WIDTH) * SUPER_SAMPLE;
|
|
||||||
*pHeight = height = vrapi_GetSystemPropertyInt(&engine->java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_HEIGHT) * SUPER_SAMPLE;
|
|
||||||
|
|
||||||
vr.fov_x = vrapi_GetSystemPropertyInt( &engine->java, VRAPI_SYS_PROP_SUGGESTED_EYE_FOV_DEGREES_X);
|
vr.fov_x = vrapi_GetSystemPropertyInt( &engine->java, VRAPI_SYS_PROP_SUGGESTED_EYE_FOV_DEGREES_X);
|
||||||
vr.fov_y = vrapi_GetSystemPropertyInt( &engine->java, VRAPI_SYS_PROP_SUGGESTED_EYE_FOV_DEGREES_Y);
|
vr.fov_y = vrapi_GetSystemPropertyInt( &engine->java, VRAPI_SYS_PROP_SUGGESTED_EYE_FOV_DEGREES_Y);
|
||||||
*/
|
*/
|
||||||
|
@ -75,10 +163,6 @@ void VR_GetResolution(engine_t* engine, int *pWidth, int *pHeight)
|
||||||
*pWidth = width;
|
*pWidth = width;
|
||||||
*pHeight = height;
|
*pHeight = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO:remove hardcoded values
|
|
||||||
*pWidth = 3664 / 2;
|
|
||||||
*pHeight = 1920;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VR_InitRenderer( engine_t* engine ) {
|
void VR_InitRenderer( engine_t* engine ) {
|
||||||
|
@ -89,33 +173,113 @@ void VR_InitRenderer( engine_t* engine ) {
|
||||||
|
|
||||||
int eyeW, eyeH;
|
int eyeW, eyeH;
|
||||||
VR_GetResolution(engine, &eyeW, &eyeH);
|
VR_GetResolution(engine, &eyeW, &eyeH);
|
||||||
ovrRenderer_Create(engine->session, &engine->renderer, eyeW, eyeH);
|
|
||||||
ovrRenderer_SetFoveation(
|
|
||||||
&engine->instance,
|
|
||||||
&engine->session,
|
|
||||||
&engine->renderer,
|
|
||||||
XR_FOVEATION_LEVEL_HIGH_FB,
|
|
||||||
0,
|
|
||||||
XR_FOVEATION_DYNAMIC_DISABLED_FB);
|
|
||||||
|
|
||||||
|
// Get the viewport configuration info for the chosen viewport configuration type.
|
||||||
|
engine->appState.ViewportConfig.type = XR_TYPE_VIEW_CONFIGURATION_PROPERTIES;
|
||||||
|
|
||||||
|
OXR(xrGetViewConfigurationProperties(
|
||||||
|
engine->appState.Instance, engine->appState.SystemId, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, &engine->appState.ViewportConfig));
|
||||||
|
|
||||||
|
// Get the supported display refresh rates for the system.
|
||||||
|
{
|
||||||
|
PFN_xrEnumerateDisplayRefreshRatesFB pfnxrEnumerateDisplayRefreshRatesFB = NULL;
|
||||||
|
OXR(xrGetInstanceProcAddr(
|
||||||
|
engine->appState.Instance,
|
||||||
|
"xrEnumerateDisplayRefreshRatesFB",
|
||||||
|
(PFN_xrVoidFunction*)(&pfnxrEnumerateDisplayRefreshRatesFB)));
|
||||||
|
|
||||||
|
OXR(pfnxrEnumerateDisplayRefreshRatesFB(
|
||||||
|
engine->appState.Session, 0, &engine->appState.NumSupportedDisplayRefreshRates, NULL));
|
||||||
|
|
||||||
|
engine->appState.SupportedDisplayRefreshRates =
|
||||||
|
(float*)malloc(engine->appState.NumSupportedDisplayRefreshRates * sizeof(float));
|
||||||
|
OXR(pfnxrEnumerateDisplayRefreshRatesFB(
|
||||||
|
engine->appState.Session,
|
||||||
|
engine->appState.NumSupportedDisplayRefreshRates,
|
||||||
|
&engine->appState.NumSupportedDisplayRefreshRates,
|
||||||
|
engine->appState.SupportedDisplayRefreshRates));
|
||||||
|
ALOGV("Supported Refresh Rates:");
|
||||||
|
for (uint32_t i = 0; i < engine->appState.NumSupportedDisplayRefreshRates; i++) {
|
||||||
|
ALOGV("%d:%f", i, engine->appState.SupportedDisplayRefreshRates[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
OXR(xrGetInstanceProcAddr(
|
||||||
|
engine->appState.Instance,
|
||||||
|
"xrGetDisplayRefreshRateFB",
|
||||||
|
(PFN_xrVoidFunction*)(&engine->appState.pfnGetDisplayRefreshRate)));
|
||||||
|
|
||||||
|
float currentDisplayRefreshRate = 0.0f;
|
||||||
|
OXR(engine->appState.pfnGetDisplayRefreshRate(engine->appState.Session, ¤tDisplayRefreshRate));
|
||||||
|
ALOGV("Current System Display Refresh Rate: %f", currentDisplayRefreshRate);
|
||||||
|
|
||||||
|
OXR(xrGetInstanceProcAddr(
|
||||||
|
engine->appState.Instance,
|
||||||
|
"xrRequestDisplayRefreshRateFB",
|
||||||
|
(PFN_xrVoidFunction*)(&engine->appState.pfnRequestDisplayRefreshRate)));
|
||||||
|
|
||||||
|
// Test requesting the system default.
|
||||||
|
OXR(engine->appState.pfnRequestDisplayRefreshRate(engine->appState.Session, 0.0f));
|
||||||
|
ALOGV("Requesting system default display refresh rate");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t numOutputSpaces = 0;
|
||||||
|
OXR(xrEnumerateReferenceSpaces(engine->appState.Session, 0, &numOutputSpaces, NULL));
|
||||||
|
|
||||||
|
XrReferenceSpaceType* referenceSpaces =
|
||||||
|
(XrReferenceSpaceType*)malloc(numOutputSpaces * sizeof(XrReferenceSpaceType));
|
||||||
|
|
||||||
|
OXR(xrEnumerateReferenceSpaces(
|
||||||
|
engine->appState.Session, numOutputSpaces, &numOutputSpaces, referenceSpaces));
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < numOutputSpaces; i++) {
|
||||||
|
if (referenceSpaces[i] == XR_REFERENCE_SPACE_TYPE_STAGE) {
|
||||||
|
stageSupported = GL_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(referenceSpaces);
|
||||||
|
|
||||||
|
// Create a space to the first path
|
||||||
XrReferenceSpaceCreateInfo spaceCreateInfo = {};
|
XrReferenceSpaceCreateInfo spaceCreateInfo = {};
|
||||||
spaceCreateInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
spaceCreateInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||||
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;
|
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW;
|
||||||
spaceCreateInfo.poseInReferenceSpace.orientation.w = 1.0f;
|
spaceCreateInfo.poseInReferenceSpace.orientation.w = 1.0f;
|
||||||
|
OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.HeadSpace));
|
||||||
|
|
||||||
|
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
||||||
|
OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.LocalSpace));
|
||||||
|
|
||||||
|
// Create a default stage space to use if SPACE_TYPE_STAGE is not
|
||||||
|
// supported, or calls to xrGetReferenceSpaceBoundsRect fail.
|
||||||
|
{
|
||||||
|
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
||||||
|
spaceCreateInfo.poseInReferenceSpace.position.y = -1.6750f;
|
||||||
|
OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.FakeStageSpace));
|
||||||
|
ALOGV("Created fake stage space from local space with offset");
|
||||||
|
engine->appState.CurrentSpace = engine->appState.FakeStageSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stageSupported) {
|
||||||
|
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;
|
||||||
spaceCreateInfo.poseInReferenceSpace.position.y = 0.0f;
|
spaceCreateInfo.poseInReferenceSpace.position.y = 0.0f;
|
||||||
xrCreateReferenceSpace(engine->session, &spaceCreateInfo, &engine->stageSpace);
|
OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.StageSpace));
|
||||||
|
ALOGV("Created stage space");
|
||||||
|
engine->appState.CurrentSpace = engine->appState.StageSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
projections = (XrView*)(malloc(ovrMaxNumEyes * sizeof(XrView)));
|
||||||
|
|
||||||
|
ovrRenderer_Create(
|
||||||
|
engine->appState.Session,
|
||||||
|
&engine->appState.Renderer,
|
||||||
|
engine->appState.ViewConfigurationView[0].recommendedImageRectWidth,
|
||||||
|
engine->appState.ViewConfigurationView[0].recommendedImageRectHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VR_DestroyRenderer( engine_t* engine ) {
|
void VR_DestroyRenderer( engine_t* engine ) {
|
||||||
xrDestroySpace(engine->stageSpace);
|
ovrRenderer_Destroy(&engine->appState.Renderer);
|
||||||
ovrRenderer_Destroy(&engine->renderer);
|
free(projections);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VR_ReInitRenderer()
|
|
||||||
{
|
|
||||||
VR_DestroyRenderer( VR_GetEngine() );
|
|
||||||
VR_InitRenderer( VR_GetEngine() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -202,88 +366,7 @@ ovrLayerCylinder2 BuildCylinderLayer(engine_t* engine, const int textureWidth, c
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void VR_ClearFrameBuffer( int width, int height )
|
|
||||||
{
|
|
||||||
|
|
||||||
glEnable( GL_SCISSOR_TEST );
|
|
||||||
glViewport( 0, 0, width, height );
|
|
||||||
|
|
||||||
if (Cvar_VariableIntegerValue("vr_thirdPersonSpectator"))
|
|
||||||
{
|
|
||||||
//Blood red.. ish
|
|
||||||
glClearColor( 0.12f, 0.0f, 0.05f, 1.0f );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Black
|
|
||||||
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
|
|
||||||
}
|
|
||||||
|
|
||||||
glScissor( 0, 0, width, height );
|
|
||||||
glClear( GL_COLOR_BUFFER_BIT );
|
|
||||||
|
|
||||||
glScissor( 0, 0, 0, 0 );
|
|
||||||
glDisable( GL_SCISSOR_TEST );
|
|
||||||
}
|
|
||||||
|
|
||||||
void VR_DrawFrame( engine_t* engine ) {
|
void VR_DrawFrame( engine_t* engine ) {
|
||||||
XrEventDataBuffer eventDataBuffer = {};
|
|
||||||
|
|
||||||
// Poll for events
|
|
||||||
for (;;) {
|
|
||||||
XrEventDataBaseHeader *baseEventHeader = (XrEventDataBaseHeader * )(&eventDataBuffer);
|
|
||||||
baseEventHeader->type = XR_TYPE_EVENT_DATA_BUFFER;
|
|
||||||
baseEventHeader->next = NULL;
|
|
||||||
if (xrPollEvent(engine->instance, &eventDataBuffer) != XR_SUCCESS) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (baseEventHeader->type == XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) {
|
|
||||||
const XrEventDataSessionStateChanged* session_state_changed_event =
|
|
||||||
(XrEventDataSessionStateChanged*)(baseEventHeader);
|
|
||||||
switch (session_state_changed_event->state) {
|
|
||||||
case XR_SESSION_STATE_READY:
|
|
||||||
if (!engine->sessionActive) {
|
|
||||||
XrSessionBeginInfo sessionBeginInfo;
|
|
||||||
memset(&sessionBeginInfo, 0, sizeof(sessionBeginInfo));
|
|
||||||
sessionBeginInfo.type = XR_TYPE_SESSION_BEGIN_INFO;
|
|
||||||
sessionBeginInfo.next = NULL;
|
|
||||||
sessionBeginInfo.primaryViewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
|
|
||||||
if (xrBeginSession(engine->session, &sessionBeginInfo) != XR_SUCCESS) {
|
|
||||||
Com_Printf("xrBeginSession failed");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
engine->sessionActive = GL_TRUE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case XR_SESSION_STATE_STOPPING:
|
|
||||||
if (engine->sessionActive) {
|
|
||||||
xrEndSession(engine->session);
|
|
||||||
engine->sessionActive = GL_FALSE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!engine->sessionActive) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: OpenXR does not use the concept of frame indices. Instead,
|
|
||||||
// XrWaitFrame returns the predicted display time.
|
|
||||||
XrFrameWaitInfo waitFrameInfo = {};
|
|
||||||
waitFrameInfo.type = XR_TYPE_FRAME_WAIT_INFO;
|
|
||||||
waitFrameInfo.next = NULL;
|
|
||||||
XrFrameState frameState = {};
|
|
||||||
frameState.type = XR_TYPE_FRAME_STATE;
|
|
||||||
frameState.next = NULL;
|
|
||||||
xrWaitFrame(engine->session, &waitFrameInfo, &frameState);
|
|
||||||
|
|
||||||
XrFrameBeginInfo beginFrameDesc = {};
|
|
||||||
beginFrameDesc.type = XR_TYPE_FRAME_BEGIN_INFO;
|
|
||||||
beginFrameDesc.next = NULL;
|
|
||||||
xrBeginFrame(engine->session, &beginFrameDesc);
|
|
||||||
|
|
||||||
float fov_y = 90; //TODO:
|
float fov_y = 90; //TODO:
|
||||||
float fov_x = 90; //TODO:
|
float fov_x = 90; //TODO:
|
||||||
|
|
||||||
|
@ -302,42 +385,80 @@ void VR_DrawFrame( engine_t* engine ) {
|
||||||
const ovrMatrix4f projectionMatrix = ovrMatrix4f_CreateProjectionFov(
|
const ovrMatrix4f projectionMatrix = ovrMatrix4f_CreateProjectionFov(
|
||||||
fov_x / vr.weapon_zoomLevel, fov_y / vr.weapon_zoomLevel, 0.0f, 0.0f, 1.0f, 0.0f );
|
fov_x / vr.weapon_zoomLevel, fov_y / vr.weapon_zoomLevel, 0.0f, 0.0f, 1.0f, 0.0f );
|
||||||
re.SetVRHeadsetParms(projectionMatrix.M,
|
re.SetVRHeadsetParms(projectionMatrix.M,
|
||||||
engine->renderer.FrameBuffer[0].FrameBuffers[engine->renderer.FrameBuffer[0].TextureSwapChainIndex],
|
engine->appState.Renderer.FrameBuffer[0].FrameBuffers[engine->appState.Renderer.FrameBuffer[0].TextureSwapChainIndex],
|
||||||
engine->renderer.FrameBuffer[1].FrameBuffers[engine->renderer.FrameBuffer[1].TextureSwapChainIndex]);
|
engine->appState.Renderer.FrameBuffer[1].FrameBuffers[engine->appState.Renderer.FrameBuffer[1].TextureSwapChainIndex]);
|
||||||
|
|
||||||
for (int eye = 0; eye < XR_EYES_COUNT; eye++) {
|
GLboolean stageBoundsDirty = GL_TRUE;
|
||||||
ovrFramebuffer* frameBuffer = &engine->renderer.FrameBuffer[eye];
|
ovrApp_HandleXrEvents(&engine->appState);
|
||||||
ovrFramebuffer_Acquire(frameBuffer);
|
if (engine->appState.SessionActive == GL_FALSE) {
|
||||||
ovrFramebuffer_SetCurrent(frameBuffer);
|
return;
|
||||||
|
|
||||||
VR_ClearFrameBuffer(frameBuffer->Width, frameBuffer->Height);
|
|
||||||
Com_Frame();
|
|
||||||
|
|
||||||
ovrFramebuffer_Resolve(frameBuffer);
|
|
||||||
ovrFramebuffer_Release(frameBuffer);
|
|
||||||
}
|
}
|
||||||
ovrFramebuffer_SetNone();
|
|
||||||
|
|
||||||
// Compose the layers for this frame.
|
if (stageBoundsDirty) {
|
||||||
XrCompositionLayerProjectionView projection_layer_elements[XR_EYES_COUNT] = {};
|
VR_UpdateStageBounds(&engine->appState);
|
||||||
XrCompositionLayerProjection projection_layer = {};
|
stageBoundsDirty = GL_FALSE;
|
||||||
projection_layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
|
}
|
||||||
projection_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
|
||||||
projection_layer.layerFlags |= XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
|
// NOTE: OpenXR does not use the concept of frame indices. Instead,
|
||||||
projection_layer.space = engine->stageSpace;
|
// XrWaitFrame returns the predicted display time.
|
||||||
projection_layer.viewCount = XR_EYES_COUNT;
|
XrFrameWaitInfo waitFrameInfo = {};
|
||||||
projection_layer.views = projection_layer_elements;
|
waitFrameInfo.type = XR_TYPE_FRAME_WAIT_INFO;
|
||||||
|
waitFrameInfo.next = NULL;
|
||||||
|
|
||||||
|
XrFrameState frameState = {};
|
||||||
|
frameState.type = XR_TYPE_FRAME_STATE;
|
||||||
|
frameState.next = NULL;
|
||||||
|
|
||||||
|
OXR(xrWaitFrame(engine->appState.Session, &waitFrameInfo, &frameState));
|
||||||
|
|
||||||
|
// Get the HMD pose, predicted for the middle of the time period during which
|
||||||
|
// the new eye images will be displayed. The number of frames predicted ahead
|
||||||
|
// depends on the pipeline depth of the engine and the synthesis rate.
|
||||||
|
// The better the prediction, the less black will be pulled in at the edges.
|
||||||
|
XrFrameBeginInfo beginFrameDesc = {};
|
||||||
|
beginFrameDesc.type = XR_TYPE_FRAME_BEGIN_INFO;
|
||||||
|
beginFrameDesc.next = NULL;
|
||||||
|
OXR(xrBeginFrame(engine->appState.Session, &beginFrameDesc));
|
||||||
|
|
||||||
|
XrSpaceLocation loc = {};
|
||||||
|
loc.type = XR_TYPE_SPACE_LOCATION;
|
||||||
|
OXR(xrLocateSpace(
|
||||||
|
engine->appState.HeadSpace, engine->appState.CurrentSpace, frameState.predictedDisplayTime, &loc));
|
||||||
|
XrPosef xfStageFromHead = loc.pose;
|
||||||
|
OXR(xrLocateSpace(
|
||||||
|
engine->appState.HeadSpace, engine->appState.LocalSpace, frameState.predictedDisplayTime, &loc));
|
||||||
|
|
||||||
|
XrViewLocateInfo projectionInfo = {};
|
||||||
|
projectionInfo.type = XR_TYPE_VIEW_LOCATE_INFO;
|
||||||
|
projectionInfo.viewConfigurationType = engine->appState.ViewportConfig.viewConfigurationType;
|
||||||
|
projectionInfo.displayTime = frameState.predictedDisplayTime;
|
||||||
|
projectionInfo.space = engine->appState.HeadSpace;
|
||||||
|
|
||||||
|
XrViewState viewState = {XR_TYPE_VIEW_STATE, NULL};
|
||||||
|
|
||||||
|
uint32_t projectionCapacityInput = ovrMaxNumEyes;
|
||||||
|
uint32_t projectionCountOutput = projectionCapacityInput;
|
||||||
|
|
||||||
|
OXR(xrLocateViews(
|
||||||
|
engine->appState.Session,
|
||||||
|
&projectionInfo,
|
||||||
|
&viewState,
|
||||||
|
projectionCapacityInput,
|
||||||
|
&projectionCountOutput,
|
||||||
|
projections));
|
||||||
|
//
|
||||||
|
|
||||||
XrPosef viewTransform[2];
|
|
||||||
ovrSceneMatrices sceneMatrices;
|
ovrSceneMatrices sceneMatrices;
|
||||||
XrView* projections = (XrView*)(malloc(XR_EYES_COUNT * sizeof(XrView)));
|
XrPosef viewTransform[2];
|
||||||
for (int eye = 0; eye < XR_EYES_COUNT; eye++) {
|
|
||||||
|
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
|
||||||
XrPosef xfHeadFromEye = projections[eye].pose;
|
XrPosef xfHeadFromEye = projections[eye].pose;
|
||||||
//XrPosef xfStageFromEye = XrPosef_Multiply(xfStageFromHead, xfHeadFromEye);
|
XrPosef xfStageFromEye = XrPosef_Multiply(xfStageFromHead, xfHeadFromEye);
|
||||||
viewTransform[eye] = XrPosef_Inverse(xfHeadFromEye); //TODO:there should be xfStageFromEye as parameter
|
viewTransform[eye] = XrPosef_Inverse(xfStageFromEye);
|
||||||
|
|
||||||
sceneMatrices.ViewMatrix[eye] =
|
sceneMatrices.ViewMatrix[eye] =
|
||||||
XrMatrix4x4f_CreateFromRigidTransform(&viewTransform[eye]);
|
XrMatrix4x4f_CreateFromRigidTransform(&viewTransform[eye]);
|
||||||
|
|
||||||
const XrFovf fov = projections[eye].fov;
|
const XrFovf fov = projections[eye].fov;
|
||||||
XrMatrix4x4f_CreateProjectionFov(
|
XrMatrix4x4f_CreateProjectionFov(
|
||||||
&sceneMatrices.ProjectionMatrix[eye],
|
&sceneMatrices.ProjectionMatrix[eye],
|
||||||
|
@ -349,17 +470,69 @@ void VR_DrawFrame( engine_t* engine ) {
|
||||||
0.0f);
|
0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int eye = 0; eye < XR_EYES_COUNT; eye++) {
|
// Set-up the compositor layers for this frame.
|
||||||
ovrFramebuffer* frameBuffer = &engine->renderer.FrameBuffer[eye];
|
// NOTE: Multiple independent layers are allowed, but they need to be added
|
||||||
|
// in a depth consistent order.
|
||||||
|
|
||||||
memset(&projection_layer_elements[eye], 0, sizeof(XrCompositionLayerProjectionView));
|
XrCompositionLayerProjectionView projection_layer_elements[2] = {};
|
||||||
|
|
||||||
|
engine->appState.LayerCount = 0;
|
||||||
|
memset(engine->appState.Layers, 0, sizeof(ovrCompositorLayer_Union) * ovrMaxLayerCount);
|
||||||
|
GLboolean shouldRenderWorldLayer = GL_TRUE;
|
||||||
|
|
||||||
|
// Render the world-view layer
|
||||||
|
if (shouldRenderWorldLayer) {
|
||||||
|
|
||||||
|
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
|
||||||
|
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer[eye];
|
||||||
|
|
||||||
|
ovrFramebuffer_Acquire(frameBuffer);
|
||||||
|
|
||||||
|
// Set the current framebuffer.
|
||||||
|
ovrFramebuffer_SetCurrent(frameBuffer);
|
||||||
|
|
||||||
|
if (Cvar_VariableIntegerValue("vr_thirdPersonSpectator"))
|
||||||
|
{
|
||||||
|
//Blood red.. ish
|
||||||
|
glClearColor( 0.12f, 0.0f, 0.05f, 1.0f );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Black
|
||||||
|
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
|
||||||
|
}
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT );
|
||||||
|
|
||||||
|
Com_Frame();
|
||||||
|
|
||||||
|
ovrFramebuffer_Resolve(frameBuffer);
|
||||||
|
|
||||||
|
ovrFramebuffer_Release(frameBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
ovrFramebuffer_SetNone();
|
||||||
|
|
||||||
|
XrCompositionLayerProjection projection_layer = {};
|
||||||
|
projection_layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
|
||||||
|
projection_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
||||||
|
projection_layer.layerFlags |= XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
|
||||||
|
projection_layer.space = engine->appState.CurrentSpace;
|
||||||
|
projection_layer.viewCount = ovrMaxNumEyes;
|
||||||
|
projection_layer.views = projection_layer_elements;
|
||||||
|
|
||||||
|
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
|
||||||
|
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer[eye];
|
||||||
|
|
||||||
|
memset(
|
||||||
|
&projection_layer_elements[eye], 0, sizeof(XrCompositionLayerProjectionView));
|
||||||
projection_layer_elements[eye].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
|
projection_layer_elements[eye].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
|
||||||
|
|
||||||
projection_layer_elements[eye].pose = XrPosef_Inverse(viewTransform[eye]);
|
projection_layer_elements[eye].pose = XrPosef_Inverse(viewTransform[eye]);
|
||||||
projection_layer_elements[eye].fov = projections[eye].fov;
|
projection_layer_elements[eye].fov = projections[eye].fov;
|
||||||
|
|
||||||
memset(&projection_layer_elements[eye].subImage, 0, sizeof(XrSwapchainSubImage));
|
memset(&projection_layer_elements[eye].subImage, 0, sizeof(XrSwapchainSubImage));
|
||||||
projection_layer_elements[eye].subImage.swapchain = frameBuffer->ColorSwapChain.Handle;
|
projection_layer_elements[eye].subImage.swapchain =
|
||||||
|
frameBuffer->ColorSwapChain.Handle;
|
||||||
projection_layer_elements[eye].subImage.imageRect.offset.x = 0;
|
projection_layer_elements[eye].subImage.imageRect.offset.x = 0;
|
||||||
projection_layer_elements[eye].subImage.imageRect.offset.y = 0;
|
projection_layer_elements[eye].subImage.imageRect.offset.y = 0;
|
||||||
projection_layer_elements[eye].subImage.imageRect.extent.width =
|
projection_layer_elements[eye].subImage.imageRect.extent.width =
|
||||||
|
@ -369,20 +542,23 @@ void VR_DrawFrame( engine_t* engine ) {
|
||||||
projection_layer_elements[eye].subImage.imageArrayIndex = 0;
|
projection_layer_elements[eye].subImage.imageArrayIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
engine->appState.Layers[engine->appState.LayerCount++].Projection = projection_layer;
|
||||||
|
}
|
||||||
|
|
||||||
// Compose the layers for this frame.
|
// Compose the layers for this frame.
|
||||||
const XrCompositionLayerBaseHeader* layers[1] = {};
|
const XrCompositionLayerBaseHeader* layers[ovrMaxLayerCount] = {};
|
||||||
layers[0] = (const XrCompositionLayerBaseHeader*)&projection_layer;
|
for (int i = 0; i < engine->appState.LayerCount; i++) {
|
||||||
|
layers[i] = (const XrCompositionLayerBaseHeader*)&engine->appState.Layers[i];
|
||||||
|
}
|
||||||
|
|
||||||
XrFrameEndInfo endFrameInfo = {};
|
XrFrameEndInfo endFrameInfo = {};
|
||||||
endFrameInfo.type = XR_TYPE_FRAME_END_INFO;
|
endFrameInfo.type = XR_TYPE_FRAME_END_INFO;
|
||||||
endFrameInfo.displayTime = frameState.predictedDisplayTime;
|
endFrameInfo.displayTime = frameState.predictedDisplayTime;
|
||||||
endFrameInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
|
endFrameInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
|
||||||
endFrameInfo.layerCount = 1;
|
endFrameInfo.layerCount = engine->appState.LayerCount;
|
||||||
endFrameInfo.layers = layers;
|
endFrameInfo.layers = layers;
|
||||||
|
|
||||||
xrEndFrame(engine->session, &endFrameInfo);
|
OXR(xrEndFrame(engine->appState.Session, &endFrameInfo));
|
||||||
free(projections);
|
|
||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -14,134 +14,12 @@ Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rig
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <android/log.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
//ID engines common
|
|
||||||
#include "../qcommon/q_shared.h"
|
|
||||||
#include "../qcommon/qcommon.h"
|
|
||||||
|
|
||||||
#if !defined(EGL_OPENGL_ES3_BIT_KHR)
|
|
||||||
#define EGL_OPENGL_ES3_BIT_KHR 0x0040
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// EXT_texture_border_clamp
|
|
||||||
#ifndef GL_CLAMP_TO_BORDER
|
|
||||||
#define GL_CLAMP_TO_BORDER 0x812D
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef GL_TEXTURE_BORDER_COLOR
|
|
||||||
#define GL_TEXTURE_BORDER_COLOR 0x1004
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(GL_EXT_multisampled_render_to_texture)
|
|
||||||
typedef void(GL_APIENTRY* PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(
|
|
||||||
GLenum target,
|
|
||||||
GLsizei samples,
|
|
||||||
GLenum internalformat,
|
|
||||||
GLsizei width,
|
|
||||||
GLsizei height);
|
|
||||||
typedef void(GL_APIENTRY* PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)(
|
|
||||||
GLenum target,
|
|
||||||
GLenum attachment,
|
|
||||||
GLenum textarget,
|
|
||||||
GLuint texture,
|
|
||||||
GLint level,
|
|
||||||
GLsizei samples);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// GL_EXT_texture_cube_map_array
|
|
||||||
#if !defined(GL_TEXTURE_CUBE_MAP_ARRAY)
|
|
||||||
#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define MATH_PI 3.14159265358979323846f
|
|
||||||
|
|
||||||
#define GL(func) func;
|
|
||||||
#define OXR(func) func;
|
|
||||||
#define OVR_LOG_TAG "XrCompositor"
|
|
||||||
|
|
||||||
#define ALOGE(...) Com_Printf(__VA_ARGS__)
|
|
||||||
#define ALOGV(...) Com_Printf(__VA_ARGS__)
|
|
||||||
|
|
||||||
const int CPU_LEVEL = 2;
|
|
||||||
const int GPU_LEVEL = 3;
|
|
||||||
const int NUM_MULTI_SAMPLES = 4;
|
const int NUM_MULTI_SAMPLES = 4;
|
||||||
|
|
||||||
typedef union {
|
|
||||||
XrCompositionLayerProjection Projection;
|
|
||||||
XrCompositionLayerQuad Quad;
|
|
||||||
XrCompositionLayerCylinderKHR Cylinder;
|
|
||||||
XrCompositionLayerCubeKHR Cube;
|
|
||||||
XrCompositionLayerEquirect2KHR Equirect2;
|
|
||||||
} ovrCompositorLayer_Union;
|
|
||||||
|
|
||||||
/*
|
|
||||||
================================================================================
|
|
||||||
|
|
||||||
OpenGL-ES Utility Functions
|
|
||||||
|
|
||||||
================================================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
const char* EglErrorString(const EGLint error) {
|
|
||||||
switch (error) {
|
|
||||||
case EGL_SUCCESS:
|
|
||||||
return "EGL_SUCCESS";
|
|
||||||
case EGL_NOT_INITIALIZED:
|
|
||||||
return "EGL_NOT_INITIALIZED";
|
|
||||||
case EGL_BAD_ACCESS:
|
|
||||||
return "EGL_BAD_ACCESS";
|
|
||||||
case EGL_BAD_ALLOC:
|
|
||||||
return "EGL_BAD_ALLOC";
|
|
||||||
case EGL_BAD_ATTRIBUTE:
|
|
||||||
return "EGL_BAD_ATTRIBUTE";
|
|
||||||
case EGL_BAD_CONTEXT:
|
|
||||||
return "EGL_BAD_CONTEXT";
|
|
||||||
case EGL_BAD_CONFIG:
|
|
||||||
return "EGL_BAD_CONFIG";
|
|
||||||
case EGL_BAD_CURRENT_SURFACE:
|
|
||||||
return "EGL_BAD_CURRENT_SURFACE";
|
|
||||||
case EGL_BAD_DISPLAY:
|
|
||||||
return "EGL_BAD_DISPLAY";
|
|
||||||
case EGL_BAD_SURFACE:
|
|
||||||
return "EGL_BAD_SURFACE";
|
|
||||||
case EGL_BAD_MATCH:
|
|
||||||
return "EGL_BAD_MATCH";
|
|
||||||
case EGL_BAD_PARAMETER:
|
|
||||||
return "EGL_BAD_PARAMETER";
|
|
||||||
case EGL_BAD_NATIVE_PIXMAP:
|
|
||||||
return "EGL_BAD_NATIVE_PIXMAP";
|
|
||||||
case EGL_BAD_NATIVE_WINDOW:
|
|
||||||
return "EGL_BAD_NATIVE_WINDOW";
|
|
||||||
case EGL_CONTEXT_LOST:
|
|
||||||
return "EGL_CONTEXT_LOST";
|
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* GlFrameBufferStatusString(GLenum status) {
|
|
||||||
switch (status) {
|
|
||||||
case GL_FRAMEBUFFER_UNDEFINED:
|
|
||||||
return "GL_FRAMEBUFFER_UNDEFINED";
|
|
||||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
|
|
||||||
return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
|
|
||||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
|
|
||||||
return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
|
|
||||||
case GL_FRAMEBUFFER_UNSUPPORTED:
|
|
||||||
return "GL_FRAMEBUFFER_UNSUPPORTED";
|
|
||||||
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
|
|
||||||
return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
|
|
||||||
default:
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
|
@ -150,6 +28,7 @@ ovrFramebuffer
|
||||||
================================================================================
|
================================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
void ovrFramebuffer_Clear(ovrFramebuffer* frameBuffer) {
|
void ovrFramebuffer_Clear(ovrFramebuffer* frameBuffer) {
|
||||||
frameBuffer->Width = 0;
|
frameBuffer->Width = 0;
|
||||||
frameBuffer->Height = 0;
|
frameBuffer->Height = 0;
|
||||||
|
@ -164,7 +43,7 @@ void ovrFramebuffer_Clear(ovrFramebuffer* frameBuffer) {
|
||||||
frameBuffer->FrameBuffers = NULL;
|
frameBuffer->FrameBuffers = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLboolean ovrFramebuffer_Create(
|
bool ovrFramebuffer_Create(
|
||||||
XrSession session,
|
XrSession session,
|
||||||
ovrFramebuffer* frameBuffer,
|
ovrFramebuffer* frameBuffer,
|
||||||
const GLenum colorFormat,
|
const GLenum colorFormat,
|
||||||
|
@ -300,8 +179,7 @@ GLboolean ovrFramebuffer_Create(
|
||||||
GL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
GL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||||
if (renderFramebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
|
if (renderFramebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
ALOGE(
|
ALOGE(
|
||||||
"Incomplete frame buffer object: %s",
|
"Incomplete frame buffer object: %d", renderFramebufferStatus);
|
||||||
GlFrameBufferStatusString(renderFramebufferStatus));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -325,8 +203,7 @@ GLboolean ovrFramebuffer_Create(
|
||||||
GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
|
GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
|
||||||
if (renderFramebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
|
if (renderFramebufferStatus != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
ALOGE(
|
ALOGE(
|
||||||
"Incomplete frame buffer object: %s",
|
"Incomplete frame buffer object: %d", renderFramebufferStatus);
|
||||||
GlFrameBufferStatusString(renderFramebufferStatus));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,8 +237,6 @@ void ovrFramebuffer_Resolve(ovrFramebuffer* frameBuffer) {
|
||||||
// Discard the depth buffer, so the tiler won't need to write it back out to memory.
|
// Discard the depth buffer, so the tiler won't need to write it back out to memory.
|
||||||
const GLenum depthAttachment[1] = {GL_DEPTH_ATTACHMENT};
|
const GLenum depthAttachment[1] = {GL_DEPTH_ATTACHMENT};
|
||||||
glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, depthAttachment);
|
glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, depthAttachment);
|
||||||
|
|
||||||
// We now let the resolve happen implicitly.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer) {
|
void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer) {
|
||||||
|
@ -400,7 +275,7 @@ ovrRenderer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ovrRenderer_Clear(ovrRenderer* renderer) {
|
void ovrRenderer_Clear(ovrRenderer* renderer) {
|
||||||
for (int eye = 0; eye < XR_EYES_COUNT; eye++) {
|
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
|
||||||
ovrFramebuffer_Clear(&renderer->FrameBuffer[eye]);
|
ovrFramebuffer_Clear(&renderer->FrameBuffer[eye]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -411,7 +286,7 @@ void ovrRenderer_Create(
|
||||||
int suggestedEyeTextureWidth,
|
int suggestedEyeTextureWidth,
|
||||||
int suggestedEyeTextureHeight) {
|
int suggestedEyeTextureHeight) {
|
||||||
// Create the frame buffers.
|
// Create the frame buffers.
|
||||||
for (int eye = 0; eye < XR_EYES_COUNT; eye++) {
|
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
|
||||||
ovrFramebuffer_Create(
|
ovrFramebuffer_Create(
|
||||||
session,
|
session,
|
||||||
&renderer->FrameBuffer[eye],
|
&renderer->FrameBuffer[eye],
|
||||||
|
@ -423,64 +298,200 @@ void ovrRenderer_Create(
|
||||||
}
|
}
|
||||||
|
|
||||||
void ovrRenderer_Destroy(ovrRenderer* renderer) {
|
void ovrRenderer_Destroy(ovrRenderer* renderer) {
|
||||||
for (int eye = 0; eye < XR_EYES_COUNT; eye++) {
|
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
|
||||||
ovrFramebuffer_Destroy(&renderer->FrameBuffer[eye]);
|
ovrFramebuffer_Destroy(&renderer->FrameBuffer[eye]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ovrRenderer_SetFoveation(
|
/*
|
||||||
XrInstance* instance,
|
================================================================================
|
||||||
XrSession* session,
|
|
||||||
ovrRenderer* renderer,
|
ovrApp
|
||||||
XrFoveationLevelFB level,
|
|
||||||
float verticalOffset,
|
================================================================================
|
||||||
XrFoveationDynamicFB dynamic) {
|
*/
|
||||||
PFN_xrCreateFoveationProfileFB pfnCreateFoveationProfileFB;
|
|
||||||
|
void ovrApp_Clear(ovrApp* app) {
|
||||||
|
app->Focused = false;
|
||||||
|
app->Instance = XR_NULL_HANDLE;
|
||||||
|
app->Session = XR_NULL_HANDLE;
|
||||||
|
memset(&app->ViewportConfig, 0, sizeof(XrViewConfigurationProperties));
|
||||||
|
memset(&app->ViewConfigurationView, 0, ovrMaxNumEyes * sizeof(XrViewConfigurationView));
|
||||||
|
app->SystemId = XR_NULL_SYSTEM_ID;
|
||||||
|
app->HeadSpace = XR_NULL_HANDLE;
|
||||||
|
app->LocalSpace = XR_NULL_HANDLE;
|
||||||
|
app->StageSpace = XR_NULL_HANDLE;
|
||||||
|
app->FakeStageSpace = XR_NULL_HANDLE;
|
||||||
|
app->CurrentSpace = XR_NULL_HANDLE;
|
||||||
|
app->SessionActive = false;
|
||||||
|
app->SupportedDisplayRefreshRates = NULL;
|
||||||
|
app->RequestedDisplayRefreshRateIndex = 0;
|
||||||
|
app->NumSupportedDisplayRefreshRates = 0;
|
||||||
|
app->pfnGetDisplayRefreshRate = NULL;
|
||||||
|
app->pfnRequestDisplayRefreshRate = NULL;
|
||||||
|
app->SwapInterval = 1;
|
||||||
|
memset(app->Layers, 0, sizeof(ovrCompositorLayer_Union) * ovrMaxLayerCount);
|
||||||
|
app->LayerCount = 0;
|
||||||
|
app->MainThreadTid = 0;
|
||||||
|
app->RenderThreadTid = 0;
|
||||||
|
app->TouchPadDownLastFrame = false;
|
||||||
|
|
||||||
|
ovrRenderer_Clear(&app->Renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ovrApp_Destroy(ovrApp* app) {
|
||||||
|
if (app->SupportedDisplayRefreshRates != NULL) {
|
||||||
|
free(app->SupportedDisplayRefreshRates);
|
||||||
|
}
|
||||||
|
|
||||||
|
ovrApp_Clear(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ovrApp_HandleSessionStateChanges(ovrApp* app, XrSessionState state) {
|
||||||
|
if (state == XR_SESSION_STATE_READY) {
|
||||||
|
assert(app->SessionActive == false);
|
||||||
|
|
||||||
|
XrSessionBeginInfo sessionBeginInfo;
|
||||||
|
memset(&sessionBeginInfo, 0, sizeof(sessionBeginInfo));
|
||||||
|
sessionBeginInfo.type = XR_TYPE_SESSION_BEGIN_INFO;
|
||||||
|
sessionBeginInfo.next = NULL;
|
||||||
|
sessionBeginInfo.primaryViewConfigurationType = app->ViewportConfig.viewConfigurationType;
|
||||||
|
|
||||||
|
XrResult result;
|
||||||
|
OXR(result = xrBeginSession(app->Session, &sessionBeginInfo));
|
||||||
|
|
||||||
|
app->SessionActive = (result == XR_SUCCESS);
|
||||||
|
|
||||||
|
// Set session state once we have entered VR mode and have a valid session object.
|
||||||
|
if (app->SessionActive) {
|
||||||
|
XrPerfSettingsLevelEXT cpuPerfLevel = XR_PERF_SETTINGS_LEVEL_BOOST_EXT;
|
||||||
|
XrPerfSettingsLevelEXT gpuPerfLevel = XR_PERF_SETTINGS_LEVEL_BOOST_EXT;
|
||||||
|
|
||||||
|
PFN_xrPerfSettingsSetPerformanceLevelEXT pfnPerfSettingsSetPerformanceLevelEXT = NULL;
|
||||||
OXR(xrGetInstanceProcAddr(
|
OXR(xrGetInstanceProcAddr(
|
||||||
*instance,
|
app->Instance,
|
||||||
"xrCreateFoveationProfileFB",
|
"xrPerfSettingsSetPerformanceLevelEXT",
|
||||||
(PFN_xrVoidFunction*)(&pfnCreateFoveationProfileFB)));
|
(PFN_xrVoidFunction*)(&pfnPerfSettingsSetPerformanceLevelEXT)));
|
||||||
|
|
||||||
PFN_xrDestroyFoveationProfileFB pfnDestroyFoveationProfileFB;
|
OXR(pfnPerfSettingsSetPerformanceLevelEXT(
|
||||||
|
app->Session, XR_PERF_SETTINGS_DOMAIN_CPU_EXT, cpuPerfLevel));
|
||||||
|
OXR(pfnPerfSettingsSetPerformanceLevelEXT(
|
||||||
|
app->Session, XR_PERF_SETTINGS_DOMAIN_GPU_EXT, gpuPerfLevel));
|
||||||
|
|
||||||
|
PFN_xrSetAndroidApplicationThreadKHR pfnSetAndroidApplicationThreadKHR = NULL;
|
||||||
OXR(xrGetInstanceProcAddr(
|
OXR(xrGetInstanceProcAddr(
|
||||||
*instance,
|
app->Instance,
|
||||||
"xrDestroyFoveationProfileFB",
|
"xrSetAndroidApplicationThreadKHR",
|
||||||
(PFN_xrVoidFunction*)(&pfnDestroyFoveationProfileFB)));
|
(PFN_xrVoidFunction*)(&pfnSetAndroidApplicationThreadKHR)));
|
||||||
|
|
||||||
PFN_xrUpdateSwapchainFB pfnUpdateSwapchainFB;
|
OXR(pfnSetAndroidApplicationThreadKHR(
|
||||||
OXR(xrGetInstanceProcAddr(
|
app->Session, XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR, app->MainThreadTid));
|
||||||
*instance, "xrUpdateSwapchainFB", (PFN_xrVoidFunction*)(&pfnUpdateSwapchainFB)));
|
OXR(pfnSetAndroidApplicationThreadKHR(
|
||||||
|
app->Session, XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR, app->RenderThreadTid));
|
||||||
|
}
|
||||||
|
} else if (state == XR_SESSION_STATE_STOPPING) {
|
||||||
|
assert(app->SessionActive);
|
||||||
|
|
||||||
for (int eye = 0; eye < XR_EYES_COUNT; eye++) {
|
OXR(xrEndSession(app->Session));
|
||||||
XrFoveationLevelProfileCreateInfoFB levelProfileCreateInfo;
|
app->SessionActive = false;
|
||||||
memset(&levelProfileCreateInfo, 0, sizeof(levelProfileCreateInfo));
|
|
||||||
levelProfileCreateInfo.type = XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB;
|
|
||||||
levelProfileCreateInfo.level = level;
|
|
||||||
levelProfileCreateInfo.verticalOffset = verticalOffset;
|
|
||||||
levelProfileCreateInfo.dynamic = dynamic;
|
|
||||||
|
|
||||||
XrFoveationProfileCreateInfoFB profileCreateInfo;
|
|
||||||
memset(&profileCreateInfo, 0, sizeof(profileCreateInfo));
|
|
||||||
profileCreateInfo.type = XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB;
|
|
||||||
profileCreateInfo.next = &levelProfileCreateInfo;
|
|
||||||
|
|
||||||
XrFoveationProfileFB foveationProfile;
|
|
||||||
|
|
||||||
pfnCreateFoveationProfileFB(*session, &profileCreateInfo, &foveationProfile);
|
|
||||||
|
|
||||||
XrSwapchainStateFoveationFB foveationUpdateState;
|
|
||||||
memset(&foveationUpdateState, 0, sizeof(foveationUpdateState));
|
|
||||||
foveationUpdateState.type = XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB;
|
|
||||||
foveationUpdateState.profile = foveationProfile;
|
|
||||||
|
|
||||||
pfnUpdateSwapchainFB(
|
|
||||||
renderer->FrameBuffer[eye].ColorSwapChain.Handle,
|
|
||||||
(XrSwapchainStateBaseHeaderFB*)(&foveationUpdateState));
|
|
||||||
|
|
||||||
pfnDestroyFoveationProfileFB(foveationProfile);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ovrApp_HandleXrEvents(ovrApp* app) {
|
||||||
|
XrEventDataBuffer eventDataBuffer = {};
|
||||||
|
|
||||||
|
// Poll for events
|
||||||
|
for (;;) {
|
||||||
|
XrEventDataBaseHeader* baseEventHeader = (XrEventDataBaseHeader*)(&eventDataBuffer);
|
||||||
|
baseEventHeader->type = XR_TYPE_EVENT_DATA_BUFFER;
|
||||||
|
baseEventHeader->next = NULL;
|
||||||
|
XrResult r;
|
||||||
|
OXR(r = xrPollEvent(app->Instance, &eventDataBuffer));
|
||||||
|
if (r != XR_SUCCESS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (baseEventHeader->type) {
|
||||||
|
case XR_TYPE_EVENT_DATA_EVENTS_LOST:
|
||||||
|
ALOGV("xrPollEvent: received XR_TYPE_EVENT_DATA_EVENTS_LOST event");
|
||||||
|
break;
|
||||||
|
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: {
|
||||||
|
const XrEventDataInstanceLossPending* instance_loss_pending_event =
|
||||||
|
(XrEventDataInstanceLossPending*)(baseEventHeader);
|
||||||
|
ALOGV(
|
||||||
|
"xrPollEvent: received XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING event: time %f",
|
||||||
|
FromXrTime(instance_loss_pending_event->lossTime));
|
||||||
|
} break;
|
||||||
|
case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
|
||||||
|
ALOGV("xrPollEvent: received XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED event");
|
||||||
|
break;
|
||||||
|
case XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT: {
|
||||||
|
const XrEventDataPerfSettingsEXT* perf_settings_event =
|
||||||
|
(XrEventDataPerfSettingsEXT*)(baseEventHeader);
|
||||||
|
ALOGV(
|
||||||
|
"xrPollEvent: received XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT event: type %d subdomain %d : level %d -> level %d",
|
||||||
|
perf_settings_event->type,
|
||||||
|
perf_settings_event->subDomain,
|
||||||
|
perf_settings_event->fromLevel,
|
||||||
|
perf_settings_event->toLevel);
|
||||||
|
} break;
|
||||||
|
case XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB: {
|
||||||
|
const XrEventDataDisplayRefreshRateChangedFB* refresh_rate_changed_event =
|
||||||
|
(XrEventDataDisplayRefreshRateChangedFB*)(baseEventHeader);
|
||||||
|
ALOGV(
|
||||||
|
"xrPollEvent: received XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB event: fromRate %f -> toRate %f",
|
||||||
|
refresh_rate_changed_event->fromDisplayRefreshRate,
|
||||||
|
refresh_rate_changed_event->toDisplayRefreshRate);
|
||||||
|
} break;
|
||||||
|
case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING: {
|
||||||
|
XrEventDataReferenceSpaceChangePending* ref_space_change_event =
|
||||||
|
(XrEventDataReferenceSpaceChangePending*)(baseEventHeader);
|
||||||
|
ALOGV(
|
||||||
|
"xrPollEvent: received XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING event: changed space: %d for session %p at time %f",
|
||||||
|
ref_space_change_event->referenceSpaceType,
|
||||||
|
(void*)ref_space_change_event->session,
|
||||||
|
FromXrTime(ref_space_change_event->changeTime));
|
||||||
|
} break;
|
||||||
|
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: {
|
||||||
|
const XrEventDataSessionStateChanged* session_state_changed_event =
|
||||||
|
(XrEventDataSessionStateChanged*)(baseEventHeader);
|
||||||
|
ALOGV(
|
||||||
|
"xrPollEvent: received XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: %d for session %p at time %f",
|
||||||
|
session_state_changed_event->state,
|
||||||
|
(void*)session_state_changed_event->session,
|
||||||
|
FromXrTime(session_state_changed_event->time));
|
||||||
|
|
||||||
|
switch (session_state_changed_event->state) {
|
||||||
|
case XR_SESSION_STATE_FOCUSED:
|
||||||
|
app->Focused = true;
|
||||||
|
break;
|
||||||
|
case XR_SESSION_STATE_VISIBLE:
|
||||||
|
app->Focused = false;
|
||||||
|
break;
|
||||||
|
case XR_SESSION_STATE_READY:
|
||||||
|
case XR_SESSION_STATE_STOPPING:
|
||||||
|
ovrApp_HandleSessionStateChanges(app, session_state_changed_event->state);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
ALOGV("xrPollEvent: Unknown event");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
ovrMatrix4f
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
ovrMatrix4f ovrMatrix4f_CreateProjection(
|
ovrMatrix4f ovrMatrix4f_CreateProjection(
|
||||||
const float minX,
|
const float minX,
|
||||||
const float maxX,
|
const float maxX,
|
||||||
|
|
|
@ -23,6 +23,35 @@
|
||||||
#include <openxr/openxr_oculus.h>
|
#include <openxr/openxr_oculus.h>
|
||||||
#include <openxr/openxr_oculus_helpers.h>
|
#include <openxr/openxr_oculus_helpers.h>
|
||||||
|
|
||||||
|
#if !defined(GL_EXT_multisampled_render_to_texture)
|
||||||
|
typedef void(GL_APIENTRY* PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(
|
||||||
|
GLenum target,
|
||||||
|
GLsizei samples,
|
||||||
|
GLenum internalformat,
|
||||||
|
GLsizei width,
|
||||||
|
GLsizei height);
|
||||||
|
typedef void(GL_APIENTRY* PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)(
|
||||||
|
GLenum target,
|
||||||
|
GLenum attachment,
|
||||||
|
GLenum textarget,
|
||||||
|
GLuint texture,
|
||||||
|
GLint level,
|
||||||
|
GLsizei samples);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ALOGE(...) printf(__VA_ARGS__)
|
||||||
|
#define ALOGV(...) printf(__VA_ARGS__)
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
XrCompositionLayerProjection Projection;
|
||||||
|
} ovrCompositorLayer_Union;
|
||||||
|
|
||||||
|
enum { ovrMaxLayerCount = 16 };
|
||||||
|
enum { ovrMaxNumEyes = 2 };
|
||||||
|
|
||||||
|
#define GL(func) func;
|
||||||
|
#define OXR(func) func;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
JavaVM* Vm;
|
JavaVM* Vm;
|
||||||
jobject ActivityObject;
|
jobject ActivityObject;
|
||||||
|
@ -48,27 +77,55 @@ typedef struct {
|
||||||
} ovrFramebuffer;
|
} ovrFramebuffer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ovrFramebuffer FrameBuffer[XR_EYES_COUNT];
|
ovrFramebuffer FrameBuffer[ovrMaxNumEyes];
|
||||||
} ovrRenderer;
|
} ovrRenderer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
XrMatrix4x4f ViewMatrix[XR_EYES_COUNT];
|
XrMatrix4x4f ViewMatrix[ovrMaxNumEyes];
|
||||||
XrMatrix4x4f ProjectionMatrix[XR_EYES_COUNT];
|
XrMatrix4x4f ProjectionMatrix[ovrMaxNumEyes];
|
||||||
} ovrSceneMatrices;
|
} ovrSceneMatrices;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GLboolean Focused;
|
||||||
|
|
||||||
|
XrInstance Instance;
|
||||||
|
XrSession Session;
|
||||||
|
XrViewConfigurationProperties ViewportConfig;
|
||||||
|
XrViewConfigurationView ViewConfigurationView[ovrMaxNumEyes];
|
||||||
|
XrSystemId SystemId;
|
||||||
|
XrSpace HeadSpace;
|
||||||
|
XrSpace LocalSpace;
|
||||||
|
XrSpace StageSpace;
|
||||||
|
XrSpace FakeStageSpace;
|
||||||
|
XrSpace CurrentSpace;
|
||||||
|
GLboolean SessionActive;
|
||||||
|
|
||||||
|
float* SupportedDisplayRefreshRates;
|
||||||
|
uint32_t RequestedDisplayRefreshRateIndex;
|
||||||
|
uint32_t NumSupportedDisplayRefreshRates;
|
||||||
|
PFN_xrGetDisplayRefreshRateFB pfnGetDisplayRefreshRate;
|
||||||
|
PFN_xrRequestDisplayRefreshRateFB pfnRequestDisplayRefreshRate;
|
||||||
|
|
||||||
|
int SwapInterval;
|
||||||
|
// These threads will be marked as performance threads.
|
||||||
|
int MainThreadTid;
|
||||||
|
int RenderThreadTid;
|
||||||
|
ovrCompositorLayer_Union Layers[ovrMaxLayerCount];
|
||||||
|
int LayerCount;
|
||||||
|
|
||||||
|
GLboolean TouchPadDownLastFrame;
|
||||||
|
ovrRenderer Renderer;
|
||||||
|
} ovrApp;
|
||||||
|
|
||||||
|
|
||||||
typedef struct ovrMatrix4f_ {
|
typedef struct ovrMatrix4f_ {
|
||||||
float M[4][4];
|
float M[4][4];
|
||||||
} ovrMatrix4f;
|
} ovrMatrix4f;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t frameIndex;
|
uint64_t frameIndex;
|
||||||
|
ovrApp appState;
|
||||||
ovrJava java;
|
ovrJava java;
|
||||||
ovrRenderer renderer;
|
|
||||||
XrInstance instance;
|
|
||||||
XrSession session;
|
|
||||||
XrSystemId systemId;
|
|
||||||
XrSpace stageSpace;
|
|
||||||
GLboolean sessionActive;
|
|
||||||
} engine_t;
|
} engine_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -87,46 +144,16 @@ typedef enum {
|
||||||
VRFM_QUERY = 99 //Used to query which mode is active
|
VRFM_QUERY = 99 //Used to query which mode is active
|
||||||
} vrFollowMode_t;
|
} vrFollowMode_t;
|
||||||
|
|
||||||
//ovrFramebuffer
|
void ovrApp_Clear(ovrApp* app);
|
||||||
void ovrFramebuffer_Clear(ovrFramebuffer* frameBuffer);
|
void ovrApp_Destroy(ovrApp* app);
|
||||||
GLboolean ovrFramebuffer_Create(
|
void ovrApp_HandleXrEvents(ovrApp* app);
|
||||||
XrSession session,
|
|
||||||
ovrFramebuffer* frameBuffer,
|
void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer);
|
||||||
const GLenum colorFormat,
|
void ovrFramebuffer_Resolve(ovrFramebuffer* frameBuffer);
|
||||||
const int width,
|
void ovrFramebuffer_Release(ovrFramebuffer* frameBuffer);
|
||||||
const int height,
|
|
||||||
const int multisamples);
|
|
||||||
void ovrFramebuffer_Destroy(ovrFramebuffer* frameBuffer);
|
|
||||||
void ovrFramebuffer_SetCurrent(ovrFramebuffer* frameBuffer);
|
void ovrFramebuffer_SetCurrent(ovrFramebuffer* frameBuffer);
|
||||||
void ovrFramebuffer_SetNone();
|
void ovrFramebuffer_SetNone();
|
||||||
void ovrFramebuffer_Resolve(ovrFramebuffer* frameBuffer);
|
|
||||||
void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer);
|
|
||||||
void ovrFramebuffer_Release(ovrFramebuffer* frameBuffer);
|
|
||||||
|
|
||||||
//ovrRenderer
|
|
||||||
void ovrRenderer_Clear(ovrRenderer* renderer);
|
|
||||||
void ovrRenderer_Create(
|
|
||||||
XrSession session,
|
|
||||||
ovrRenderer* renderer,
|
|
||||||
int suggestedEyeTextureWidth,
|
|
||||||
int suggestedEyeTextureHeight);
|
|
||||||
void ovrRenderer_Destroy(ovrRenderer* renderer);
|
|
||||||
void ovrRenderer_SetFoveation(
|
|
||||||
XrInstance* instance,
|
|
||||||
XrSession* session,
|
|
||||||
ovrRenderer* renderer,
|
|
||||||
XrFoveationLevelFB level,
|
|
||||||
float verticalOffset,
|
|
||||||
XrFoveationDynamicFB dynamic);
|
|
||||||
|
|
||||||
//ovrMatrix4f
|
|
||||||
ovrMatrix4f ovrMatrix4f_CreateProjection(
|
|
||||||
const float minX,
|
|
||||||
const float maxX,
|
|
||||||
float const minY,
|
|
||||||
const float maxY,
|
|
||||||
const float nearZ,
|
|
||||||
const float farZ);
|
|
||||||
ovrMatrix4f ovrMatrix4f_CreateProjectionFov(
|
ovrMatrix4f ovrMatrix4f_CreateProjectionFov(
|
||||||
const float fovDegreesX,
|
const float fovDegreesX,
|
||||||
const float fovDegreesY,
|
const float fovDegreesY,
|
||||||
|
@ -135,4 +162,11 @@ ovrMatrix4f ovrMatrix4f_CreateProjectionFov(
|
||||||
const float nearZ,
|
const float nearZ,
|
||||||
const float farZ);
|
const float farZ);
|
||||||
|
|
||||||
|
void ovrRenderer_Create(
|
||||||
|
XrSession session,
|
||||||
|
ovrRenderer* renderer,
|
||||||
|
int suggestedEyeTextureWidth,
|
||||||
|
int suggestedEyeTextureHeight);
|
||||||
|
void ovrRenderer_Destroy(ovrRenderer* renderer);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue