#include #include #include #include #include #include #include #include sig_atomic_t stop = false; void handler(int sig) { stop = true; } #define HEADLESS_EXT "XR_MND_headless" static const char* xr_strerror(XrInstance instance, XrResult err) { static char buffer[XR_MAX_RESULT_STRING_SIZE]; xrResultToString(instance, err, buffer); return buffer; } void clear() { puts("\033[H\033[J"); } int main(int argc, char** argv) { XrInstance instance; XrApplicationInfo applicationInfo = { .applicationName = "OpenXR Example", .engineName = "Example Engine", .apiVersion = XR_API_VERSION_1_0, }; uint32_t extentionPropCount; xrEnumerateInstanceExtensionProperties(NULL, 0, &extentionPropCount, NULL); XrExtensionProperties *proparties = calloc(extentionPropCount, sizeof(*proparties)); for (uint32_t i = 0; i < extentionPropCount; ++i) proparties[i].type = XR_TYPE_EXTENSION_PROPERTIES; XrResult result = xrEnumerateInstanceExtensionProperties(NULL, extentionPropCount, &extentionPropCount, proparties); if (!XR_SUCCEEDED(result)) { printf("Failed to query OpenXR extensions: %d\n", result); return 1; } printf("OpenXR extensions: %d\n", extentionPropCount); bool foundHeadless = false; for (uint32_t i = 0; i < extentionPropCount; ++i) { printf("\t%s\n", proparties[i].extensionName); if (strcmp(HEADLESS_EXT, proparties[i].extensionName) == 0) foundHeadless = true; } if (!foundHeadless) { puts("Runtime dose not support " HEADLESS_EXT); return 1; } const char *enabledExtensionNames[] = {HEADLESS_EXT, NULL}; XrInstanceCreateInfo createInfo = { .type = XR_TYPE_INSTANCE_CREATE_INFO, .next = NULL, .createFlags = 0, .applicationInfo = applicationInfo, .enabledExtensionNames = enabledExtensionNames, .enabledExtensionCount = 1 }; XrSystemGetInfo getInfo = { .type = XR_TYPE_SYSTEM_GET_INFO, .formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY }; result = xrCreateInstance(&createInfo, &instance); if (XR_SUCCEEDED(result)) { printf("OpenXR instance created successfully.\n"); } else { printf("Failed to create OpenXR instance: %d\n", result); return 1; } XrSystemId systemId; result = xrGetSystem(instance, &getInfo, &systemId); if (!XR_SUCCEEDED(result)) { printf("Failed to get OpenXR system: %s\n", xr_strerror(instance, result)); return 1; } uint32_t viewCount; result = xrEnumerateViewConfigurationViews(instance, systemId, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, 0, &viewCount, NULL); XrViewConfigurationView* viewConfigs = calloc(viewCount, sizeof(XrViewConfigurationView)); for (size_t i = 0; i < viewCount; ++i) viewConfigs[i].type = XR_TYPE_VIEW_CONFIGURATION_VIEW; if (XR_SUCCEEDED(result)) { result = xrEnumerateViewConfigurationViews(instance, systemId, XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, viewCount, &viewCount, viewConfigs); if (!XR_SUCCEEDED(result)) { printf("Failed to enumerate viewConfigs: %d\n", result); return 1; } } XrSession session; XrSessionCreateInfo createSessionInfo = { .type = XR_TYPE_SESSION_CREATE_INFO, .systemId = systemId }; result = xrCreateSession(instance, &createSessionInfo, &session); if (!XR_SUCCEEDED(result)) { printf("Failed to create session: %s\n", xr_strerror(instance, result)); return 1; } XrSessionBeginInfo beginInfo = {.type = XR_TYPE_SESSION_BEGIN_INFO, .primaryViewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO}; result = xrBeginSession(session, &beginInfo); XrSpace stageSpace; XrReferenceSpaceCreateInfo spaceCreateInfo = { .type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO, .referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE }; spaceCreateInfo.poseInReferenceSpace.orientation.x = 1; result = xrCreateReferenceSpace(session, &spaceCreateInfo, &stageSpace); if (!XR_SUCCEEDED(result)) { printf("Failed to create referance space: %s\n", xr_strerror(instance, result)); return 1; } struct timespec duration = {.tv_sec = 1}; nanosleep(&duration, NULL); XrView *views = calloc(viewCount, sizeof(*views)); for (size_t i = 0; i < viewCount; ++i) views[i].type = XR_TYPE_VIEW; XrViewState state = {.type = XR_TYPE_VIEW_STATE}; signal(SIGTERM, handler); signal(SIGHUP, handler); signal(SIGINT, handler); while(!stop) { XrFrameWaitInfo waitInfo = {.type = XR_TYPE_FRAME_WAIT_INFO}; XrFrameState frameState = {.type = XR_TYPE_FRAME_STATE}; result = xrWaitFrame(session, &waitInfo, &frameState); if (!XR_SUCCEEDED(result)) { printf("Failed to wait for frame: %s\n", xr_strerror(instance, result)); return 1; } else { printf("waited for frame time: %lu\n", frameState.predictedDisplayPeriod); } XrViewLocateInfo locateInfo = { .type = XR_TYPE_VIEW_LOCATE_INFO, .viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, .space = stageSpace, .displayTime = frameState.predictedDisplayTime+1 }; uint32_t locatedViews; result = xrLocateViews(session, &locateInfo, &state, viewCount, &locatedViews, views); if (!XR_SUCCEEDED(result)) { printf("Failed to locate views: %s\n", xr_strerror(instance, result)); struct timespec duration = {.tv_nsec = 1000*100}; nanosleep(&duration, NULL); continue; } else if (locatedViews != viewCount) { printf("Failed to locate all views"); struct timespec duration = {.tv_nsec = 1000*100}; nanosleep(&duration, NULL); continue; } clear(); for (size_t i = 0; i < viewCount; ++i) { printf("View %zu:\n", i); printf("\tRecommended Size: %d x %d\n", viewConfigs[i].recommendedImageRectWidth, viewConfigs[i].recommendedImageRectHeight); printf("\tFOV:\n\t\tUP: %f\n\t\tDOWN: %f\n\t\tLEFT: %f\n\t\tRIGHT: %f\n", views[i].fov.angleUp, views[i].fov.angleDown, views[i].fov.angleLeft, views[i].fov.angleRight); printf("\tPOS:\n\t\tX: %f\n\t\tY: %f\n\t\tZ: %f\n", views[i].pose.position.x, views[i].pose.position.y, views[i].pose.position.z); } struct timespec duration = {.tv_nsec = 1000*100}; nanosleep(&duration, NULL); } xrEndSession(session); free(views); free(viewConfigs); xrDestroySpace(stageSpace); xrDestroySession(session); xrDestroyInstance(instance); return 0; }