Collecting System Information
Getting a valid system ID that represents the device that the runtime is running on can only happen after the app receives a valid instance from xrCreateInstance
, but before a session is created or begins. The system ID represents a system type that the app uses to ask for a system of a specific type.
Specify a desired form factor, and then the runtime returns an XrSystemId
atom after calling xrGetSystem
. A valid XrSystemId
corresponds to a system that is both active and supported. The form factor is the desired system configuration.
OpenXR currently supports two form factors: XR_FORM_FACTOR_HANDHELD_DISPLAY
and XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY
. As an app developer for head-mounted XR systems, you’re likely only interested in XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY
.
If multiple systems are active on the same runtime (for example, HTC Vive and a Quest connected over Link), the app can’t choose the system. OpenXR APIs don’t support listing available systems and picking one; the runtime sets up a way for the user to decide. On Oculus PC, the selected system in the Oculus desktop application is used, but a single system is always returned in all cases.
After retrieving a system ID, the app must handle additional system information:
- View configuration: The number of views presented to the user for mono and stereo, supporting camera AR technologies and VR/MR devices (the main ones being
XR_VIEW_CONFIGURATION_PRIMARY_MONO
for single screen and XR_VIEW_CONFIGURATION_PRIMARY_STEREO
for dual screen or one screen per eye). Apps pick a supported view configuration when starting a session with xrBeginSession()
. If the system doesn’t support that view configuration, it returns XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED
. Use XrSystemId
to list supported view configurations, in order of preference, and the app should pick the first one the app supports. - Supported environment blend modes. This refers to blend modes that the system supports. These include: the enum value of
XR_ENVIRONMENT_BLEND_MODE_OPAQUE
, which mostly relates to VR systems where the composition layers do not display a view of the physical world behind them, XR_ENVIRONMENT_BLEND_MODE_ADDITIVE
, which typically relates to MR systems where the composition layers blend additively with the real world, and XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND
, which typically refers to AR handheld hardware or passthrough technologies where the composition layers are alpha-blended with the real world. The app can pick a different blend mode for each frame.
Meta devices currently only support XR_ENVIRONMENT_BLEND_MODE_OPAQUE
on Quest and Rift.
Defining the form factor in the Khronos Group’s
hello_xr sample app works as follows:
An XrFormFactor
variable is initially set to XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY
and used as an output parameter of xrGetSystem
. The latter is passed in as XR_NULL_SYSTEM_ID
, and if xrGetSystem
is successful, it’s set to the active system’s ID. Later, the app requests the active system using that form factor.
XrFormFactor m_formFactor{XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY};
...
XrSystemId m_systemId{XR_NULL_SYSTEM_ID};
...
XrSystemGetInfo systemInfo{XR_TYPE_SYSTEM_GET_INFO};
systemInfo.formFactor = m_formFactor;
CHECK_XRCMD(xrGetSystem(m_instance, &systemInfo, &m_systemId));
Create the instance before getting the system, and m_instance
must be a valid handle. Initially, m_systemId
is XR_NULL_SYSTEM_ID
, referring to an invalid system, and is expected to change depending on the active system the app runs on.
If successful, xrGetSystem
returns XR_SUCCESS
. Invalid return codes are:
XR_ERROR_VALIDATION_FAILURE
XR_ERROR_RUNTIME_FAILURE
XR_ERROR_HANDLE_INVALID
XR_ERROR_INSTANCE_LOST
XR_ERROR_FORM_FACTOR_UNSUPPORTED
XR_ERROR_FORM_FACTOR_UNAVAILABLE
- If the system doesn’t support a given form factor,
xrGetSystem
will return error code XR_ERROR_FORM_FACTOR_UNSUPPORTED
. Note: All of Meta’s OpenXR runtimes will return this if an app requests XR_FORM_FACTOR_HANDHELD_DISPLAY
. - If the system could be supported but currently is not available, the runtime will return
XR_ERROR_FORM_FACTOR_UNAVAILABLE
. Note: This doesn’t happen on Quest 1 or Quest 2, but on PC that’s what happens if the app attempts to start when the Rift or Link connection is not available.
Later on, the app uses the m_systemId
and the instance handle to create a session and initialize the Graphics API.
OpenXR apps represent view configurations through an
XrViewConfigurationType
enum (most frequently
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO
or
XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO
). Khronos’s
hello_xr sample app receives this information as follows.
An XrViewConfigurationType
member variable is initially defined and set to:
XrViewConfigurationType m_viewConfigType{XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO};
The most important functions of the View Configuration API are:
The following code snippet stores the number of view configuration types supported by a system in a viewConfigTypeCount
variable. It also stores the actual types in a vector called viewConfigTypes
:
uint32_t viewConfigTypeCount;
CHECK_XRCMD(xrEnumerateViewConfigurations(m_instance, m_systemId, 0, &viewConfigTypeCount, nullptr));
std::vector<XrViewConfigurationType> viewConfigTypes(viewConfigTypeCount);
CHECK_XRCMD(xrEnumerateViewConfigurations(m_instance, m_systemId, viewConfigTypeCount, &viewConfigTypeCount,
viewConfigTypes.data()));
CHECK((uint32_t)viewConfigTypes.size() == viewConfigTypeCount);
This uses the OpenXR two-call idiom where multiple values return by calling the function twice. For details about this OpenXR feature in function calls, read the Two-call Idiom section in
Core Concepts.
Retrieving xrGetViewConfigurationProperties
of eachXrViewConfigurationType
stored in the viewConfigTypes
vector occurs within a loop, such as:
for (XrViewConfigurationType viewConfigType : viewConfigTypes) {
...
XrViewConfigurationProperties viewConfigProperties{XR_TYPE_VIEW_CONFIGURATION_PROPERTIES};
CHECK_XRCMD(xrGetViewConfigurationProperties(m_instance, m_systemId, viewConfigType, &viewConfigProperties));
Then, details per view element are stored in an XrViewConfigurationView
vector as follows:
uint32_t viewCount;
CHECK_XRCMD(xrEnumerateViewConfigurationViews(m_instance, m_systemId, viewConfigType, 0, &viewCount, nullptr));
if (viewCount > 0) {
std::vector<XrViewConfigurationView> views(viewCount, {XR_TYPE_VIEW_CONFIGURATION_VIEW});
CHECK_XRCMD(xrEnumerateViewConfigurationViews(m_instance, m_systemId, viewConfigType, viewCount, &viewCount, views.data()));
An XrEnvironmentBlendMode
variable is initially defined as:
XrEnvironmentBlendMode m_environmentBlendMode{XR_ENVIRONMENT_BLEND_MODE_OPAQUE};
Blend modes are stored as an
XrEnvironmentBlendMode
enum value. Calling
xrEnumerateEnvironmentBlendModes
retrieves environment blend modes for a system. (This also uses the
OpenXR two-call idiom.)
uint32_t count;
CHECK_XRCMD(xrEnumerateEnvironmentBlendModes(m_instance, m_systemId, type, 0, &count, nullptr));
...
std::vector<XrEnvironmentBlendMode> blendModes(count);
CHECK_XRCMD(xrEnumerateEnvironmentBlendModes(m_instance, m_systemId, type, count, &count, blendModes.data()));
Where count
stores the number of supported blend modes and type
is the XrViewConfigurationType
.