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