File openxr.cpp
File List > openxr > openxr.cpp
Go to the documentation of this file
#ifndef XR_NO_PROTOTYPES
#define XR_NO_PROTOTYPES
#endif
#include "interface.h"
#include "openxr/openxr_loader_negotiation.h"
#include <cstring>
#include <malloc.h>
#include <string>
#define INTERFACE_VERSION 1
#define API_VERSION 1
#define PRINT_ERROR(...) \
do { \
fprintf(stderr, __VA_ARGS__); \
} while (0)
const std::string kLayerName = "ILLIXR_HT";
PFN_xrGetInstanceProcAddr nextXrGetInstanceProcAddr = nullptr;
PFN_xrEnumerateInstanceExtensionProperties NextEnumerateInstanceExtensionProperties{nullptr};
XrResult illixr_xrEnumerateInstanceExtensionProperties(const char* layerName, uint32_t propertyCapacityInput,
uint32_t* propertyCountOutput, XrExtensionProperties* properties) {
// The OpenXR specification says that this should work without an instance,
// however, a 'next' pointer is needed to query extensions that might be
// provided by another API layer, and the OpenXR *Loader* spec says:
//
// "an implicit API layer, it must add its own instance extension
// contents to the list of extensions."; this means we - and any lower
// layers - need the 'next' pointer.
if (propertyCountOutput == ((void*) nullptr)) {
return XR_ERROR_VALIDATION_FAILURE;
}
if (layerName == NULL && NextEnumerateInstanceExtensionProperties) {
return NextEnumerateInstanceExtensionProperties(layerName, propertyCapacityInput, propertyCountOutput, properties);
}
*propertyCountOutput = 0;
return XR_SUCCESS;
}
XrResult illixr_xrEnumerateApiLayerProperties(uint32_t propertyCapacityInput, uint32_t* propertyCountOutput,
XrApiLayerProperties* properties) {
if (propertyCapacityInput == 0) {
return XR_ERROR_SIZE_INSUFFICIENT;
}
// set the properties
*properties = XrApiLayerProperties{
.type = XR_TYPE_API_LAYER_PROPERTIES,
.specVersion = XR_CURRENT_API_VERSION,
.layerVersion = 1,
.description = "ILLIXR hand tracking",
};
std::strncpy(properties->layerName, kLayerName.c_str(), XR_MAX_API_LAYER_NAME_SIZE);
*propertyCountOutput = 1;
return XR_SUCCESS;
}
XrResult illixr_xrCreateApiLayerInstance(const XrInstanceCreateInfo* info, const XrApiLayerCreateInfo* layerInfo,
XrInstance* instance) {
std::string lname = layerInfo->nextInfo->layerName;
// do some error checking
if (layerInfo->structType != XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO ||
layerInfo->structVersion != XR_API_LAYER_CREATE_INFO_STRUCT_VERSION ||
layerInfo->structSize < sizeof(XrApiLayerCreateInfo) || layerInfo->nextInfo == ((void*) 0) ||
layerInfo->nextInfo->structType != XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO ||
layerInfo->nextInfo->structVersion != XR_API_LAYER_NEXT_INFO_STRUCT_VERSION ||
layerInfo->nextInfo->structSize < sizeof(XrApiLayerNextInfo) || kLayerName != lname ||
layerInfo->nextInfo->nextGetInstanceProcAddr == ((void*) 0) ||
layerInfo->nextInfo->nextCreateApiLayerInstance == ((void*) 0)) {
return XR_ERROR_INITIALIZATION_FAILED;
}
auto nextLayerCreateInfo = *layerInfo;
nextLayerCreateInfo.nextInfo = layerInfo->nextInfo->next;
// initialize down the stream
auto res = layerInfo->nextInfo->nextCreateApiLayerInstance(info, &nextLayerCreateInfo, instance);
if (XR_FAILED(res)) {
return res;
}
nextXrGetInstanceProcAddr = layerInfo->nextInfo->nextGetInstanceProcAddr;
if (nextXrGetInstanceProcAddr == NULL)
return XR_ERROR_HANDLE_INVALID;
// set the handle for our version of xrGetInstanceProcAddr
nextXrGetInstanceProcAddr(*instance, "xrEnumerateInstanceExtensionProperties",
reinterpret_cast<PFN_xrVoidFunction*>(&NextEnumerateInstanceExtensionProperties));
return res;
}
XrResult XRAPI_CALL illixr_xrGetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function) {
std::string f_name = name;
// Must be supported without an instance
// get the function pointer to the requested method
if (f_name == "xrEnumerateInstanceExtensionProperties") {
*function = (PFN_xrVoidFunction) &illixr_xrEnumerateInstanceExtensionProperties;
return XR_SUCCESS;
}
if (f_name == "xrEnumerateApiLayerProperties") {
*function = reinterpret_cast<PFN_xrVoidFunction>(&illixr_xrEnumerateApiLayerProperties);
return XR_SUCCESS;
}
if (!(instance && nextXrGetInstanceProcAddr)) {
return XR_ERROR_HANDLE_INVALID;
}
*function = nullptr;
const auto ret = nextXrGetInstanceProcAddr(instance, name, function);
if (XR_FAILED(ret) || !*function) {
return ret;
}
if (f_name == "xrCreateHandTrackerEXT") {
*function = reinterpret_cast<PFN_xrVoidFunction>(&illixr_xrCreateHandTrackerEXT);
return ret;
}
if (f_name == "xrDestroyHandTrackerEXT") {
*function = reinterpret_cast<PFN_xrVoidFunction>(&illixr_xrDestroyHandTrackerEXT);
return ret;
}
if (f_name == "xrLocateHandJointsEXT") {
*function = reinterpret_cast<PFN_xrVoidFunction>(&illixr_xrLocateHandJointsEXT);
return ret;
}
return ret;
}
#ifdef __cplusplus
extern "C" {
#endif
[[maybe_unused]] XrResult illixr_xrNegotiateLoaderApiLayerInterface(const XrNegotiateLoaderInfo* loaderInfo,
const char* layerName,
XrNegotiateApiLayerRequest* layerRequest) {
std::string lname = layerName;
if (lname != kLayerName)
return XR_ERROR_INITIALIZATION_FAILED;
// do some error checking
if (loaderInfo == ((void*) 0) || loaderInfo->structType != XR_LOADER_INTERFACE_STRUCT_LOADER_INFO ||
loaderInfo->structSize != sizeof(XrNegotiateLoaderInfo) || loaderInfo->structVersion != XR_LOADER_INFO_STRUCT_VERSION) {
return XR_ERROR_INITIALIZATION_FAILED;
}
if (layerRequest == ((void*) 0) || layerRequest->structType != XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST ||
layerRequest->structVersion != XR_API_LAYER_INFO_STRUCT_VERSION ||
layerRequest->structSize != sizeof(XrNegotiateApiLayerRequest)) {
return XR_ERROR_INITIALIZATION_FAILED;
}
if (loaderInfo->minInterfaceVersion > INTERFACE_VERSION || loaderInfo->maxInterfaceVersion < INTERFACE_VERSION) {
PRINT_ERROR("ILLIXR ht only supports OpenXR version %d which is not between the requested %d and %d\n",
INTERFACE_VERSION, loaderInfo->minInterfaceVersion, loaderInfo->maxInterfaceVersion);
return XR_ERROR_INITIALIZATION_FAILED;
}
layerRequest->layerInterfaceVersion = XR_CURRENT_LOADER_API_LAYER_VERSION;
layerRequest->layerApiVersion = API_VERSION;
// set function addresses
layerRequest->getInstanceProcAddr = reinterpret_cast<PFN_xrGetInstanceProcAddr>(illixr_xrGetInstanceProcAddr);
layerRequest->createApiLayerInstance = reinterpret_cast<PFN_xrCreateApiLayerInstance>(illixr_xrCreateApiLayerInstance);
return XR_SUCCESS;
}
#ifdef __cplusplus
}
#endif