1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "device/vr/openxr/openxr_util.h"
6
7 #include <string>
8
9 #include "base/check_op.h"
10 #include "base/stl_util.h"
11 #include "base/version.h"
12 #include "base/win/scoped_handle.h"
13 #include "build/build_config.h"
14 #include "components/version_info/version_info.h"
15
16 namespace device {
17
PoseIdentity()18 XrPosef PoseIdentity() {
19 XrPosef pose{};
20 pose.orientation.w = 1;
21 return pose;
22 }
23
GetSystem(XrInstance instance,XrSystemId * system)24 XrResult GetSystem(XrInstance instance, XrSystemId* system) {
25 XrSystemGetInfo system_info = {XR_TYPE_SYSTEM_GET_INFO};
26 system_info.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
27 return xrGetSystem(instance, &system_info, system);
28 }
29
30 #if defined(OS_WIN)
IsRunningInWin32AppContainer()31 bool IsRunningInWin32AppContainer() {
32 base::win::ScopedHandle scopedProcessToken;
33 HANDLE processToken;
34 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &processToken)) {
35 return false;
36 }
37
38 scopedProcessToken.Set(processToken);
39
40 BOOL isAppContainer;
41 DWORD dwSize = sizeof(BOOL);
42 if (!GetTokenInformation(scopedProcessToken.Get(), TokenIsAppContainer,
43 &isAppContainer, dwSize, &dwSize)) {
44 return false;
45 }
46
47 return isAppContainer;
48 }
49 #else
IsRunningInWin32AppContainer()50 bool IsRunningInWin32AppContainer() {
51 return false;
52 }
53 #endif
54
CreateInstance(XrInstance * instance,const OpenXrExtensionEnumeration & extension_enumeration)55 XrResult CreateInstance(
56 XrInstance* instance,
57 const OpenXrExtensionEnumeration& extension_enumeration) {
58 XrInstanceCreateInfo instance_create_info = {XR_TYPE_INSTANCE_CREATE_INFO};
59
60 std::string application_name = version_info::GetProductName() + " " +
61 version_info::GetMajorVersionNumber();
62 errno_t error =
63 strcpy_s(instance_create_info.applicationInfo.applicationName,
64 base::size(instance_create_info.applicationInfo.applicationName),
65 application_name.c_str());
66 DCHECK_EQ(error, 0);
67
68 base::Version version = version_info::GetVersion();
69 DCHECK_EQ(version.components().size(), 4uLL);
70 uint32_t build = version.components()[2];
71
72 // application version will be the build number of each vendor
73 instance_create_info.applicationInfo.applicationVersion = build;
74
75 error = strcpy_s(instance_create_info.applicationInfo.engineName,
76 base::size(instance_create_info.applicationInfo.engineName),
77 "Chromium");
78 DCHECK_EQ(error, 0);
79
80 // engine version should be the build number of chromium
81 instance_create_info.applicationInfo.engineVersion = build;
82
83 instance_create_info.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
84
85 // xrCreateInstance validates the list of extensions and returns
86 // XR_ERROR_EXTENSION_NOT_PRESENT if an extension is not supported,
87 // so we don't need to call xrEnumerateInstanceExtensionProperties
88 // to validate these extensions.
89 // Since the OpenXR backend only knows how to draw with D3D11 at the moment,
90 // the XR_KHR_D3D11_ENABLE_EXTENSION_NAME is required.
91 std::vector<const char*> extensions{XR_KHR_D3D11_ENABLE_EXTENSION_NAME};
92
93 // If we are in an app container, we must require the app container extension
94 // to ensure robust execution of the OpenXR runtime
95 if (IsRunningInWin32AppContainer()) {
96 // Add the win32 app container compatible extension to our list of
97 // extensions. If this runtime does not support execution in an app
98 // container environment, one of xrCreateInstance or xrGetSystem will fail.
99 extensions.push_back(XR_EXT_WIN32_APPCONTAINER_COMPATIBLE_EXTENSION_NAME);
100 }
101
102 // XR_MSFT_UNBOUNDED_REFERENCE_SPACE_EXTENSION_NAME, is required for optional
103 // functionality (unbounded reference spaces) and thus only requested if it is
104 // available.
105 const bool unboundedSpaceExtensionSupported =
106 extension_enumeration.ExtensionSupported(
107 XR_MSFT_UNBOUNDED_REFERENCE_SPACE_EXTENSION_NAME);
108 if (unboundedSpaceExtensionSupported) {
109 extensions.push_back(XR_MSFT_UNBOUNDED_REFERENCE_SPACE_EXTENSION_NAME);
110 }
111
112 // Input extensions. These enable interaction profiles not defined in the core
113 // spec
114 const bool samsungInteractionProfileExtensionSupported =
115 extension_enumeration.ExtensionSupported(
116 kExtSamsungOdysseyControllerExtensionName);
117 if (samsungInteractionProfileExtensionSupported) {
118 extensions.push_back(kExtSamsungOdysseyControllerExtensionName);
119 }
120
121 const bool hpControllerExtensionSupported =
122 extension_enumeration.ExtensionSupported(
123 kExtHPMixedRealityControllerExtensionName);
124 if (hpControllerExtensionSupported) {
125 extensions.push_back(kExtHPMixedRealityControllerExtensionName);
126 }
127
128 const bool handInteractionExtensionSupported =
129 extension_enumeration.ExtensionSupported(
130 kMSFTHandInteractionExtensionName);
131 if (handInteractionExtensionSupported) {
132 extensions.push_back(kMSFTHandInteractionExtensionName);
133 }
134
135 instance_create_info.enabledExtensionCount =
136 static_cast<uint32_t>(extensions.size());
137 instance_create_info.enabledExtensionNames = extensions.data();
138
139 return xrCreateInstance(&instance_create_info, instance);
140 }
141
GetSupportedBlendModes(XrInstance instance,XrSystemId system)142 std::vector<XrEnvironmentBlendMode> GetSupportedBlendModes(XrInstance instance,
143 XrSystemId system) {
144 // Query the list of supported environment blend modes for the current system.
145 uint32_t blend_mode_count;
146 const XrViewConfigurationType kSupportedViewConfiguration =
147 XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
148 if (XR_FAILED(xrEnumerateEnvironmentBlendModes(instance, system,
149 kSupportedViewConfiguration, 0,
150 &blend_mode_count, nullptr)))
151 return {}; // empty vector
152
153 std::vector<XrEnvironmentBlendMode> environment_blend_modes(blend_mode_count);
154 if (XR_FAILED(xrEnumerateEnvironmentBlendModes(
155 instance, system, kSupportedViewConfiguration, blend_mode_count,
156 &blend_mode_count, environment_blend_modes.data())))
157 return {}; // empty vector
158
159 return environment_blend_modes;
160 }
161
162 } // namespace device
163