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 <wrl.h>
6 
7 #include "base/stl_util.h"
8 #include "device/vr/openxr/openxr_util.h"
9 #include "device/vr/openxr/test/openxr_negotiate.h"
10 #include "device/vr/openxr/test/openxr_test_helper.h"
11 
12 namespace {
13 // Global test helper that communicates with the test and contains the mock
14 // OpenXR runtime state/properties. A reference to this is returned as the
15 // instance handle through xrCreateInstance.
16 OpenXrTestHelper g_test_helper;
17 }  // namespace
18 
19 // Extension methods
20 
21 // Mock implementations of openxr runtime.dll APIs.
22 // Please add new APIs in alphabetical order.
23 
xrAcquireSwapchainImage(XrSwapchain swapchain,const XrSwapchainImageAcquireInfo * acquire_info,uint32_t * index)24 XrResult xrAcquireSwapchainImage(
25     XrSwapchain swapchain,
26     const XrSwapchainImageAcquireInfo* acquire_info,
27     uint32_t* index) {
28   DVLOG(2) << __FUNCTION__;
29   RETURN_IF_XR_FAILED(g_test_helper.ValidateSwapchain(swapchain));
30   RETURN_IF(acquire_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
31             "XrSwapchainImageAcquireInfo is nullptr");
32   RETURN_IF(acquire_info->type != XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO,
33             XR_ERROR_VALIDATION_FAILURE,
34             "xrAcquireSwapchainImage type invalid");
35   RETURN_IF(acquire_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
36             "xrAcquireSwapchainImage next not nullptr");
37 
38   RETURN_IF(index == nullptr, XR_ERROR_VALIDATION_FAILURE,
39             "xrAcquireSwapchainImage index is nullptr");
40   *index = g_test_helper.NextSwapchainImageIndex();
41 
42   return XR_SUCCESS;
43 }
44 
xrAttachSessionActionSets(XrSession session,const XrSessionActionSetsAttachInfo * attach_info)45 XrResult xrAttachSessionActionSets(
46     XrSession session,
47     const XrSessionActionSetsAttachInfo* attach_info) {
48   DVLOG(2) << __FUNCTION__;
49   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
50   RETURN_IF(attach_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
51             "XrSessionActionSetsAttachInfo is nullptr");
52   RETURN_IF_XR_FAILED(g_test_helper.AttachActionSets(*attach_info));
53 
54   return XR_SUCCESS;
55 }
56 
xrBeginFrame(XrSession session,const XrFrameBeginInfo * frame_begin_info)57 XrResult xrBeginFrame(XrSession session,
58                       const XrFrameBeginInfo* frame_begin_info) {
59   DVLOG(2) << __FUNCTION__;
60   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
61   RETURN_IF(frame_begin_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
62             "XrFrameBeginInfo is nullptr");
63   RETURN_IF(frame_begin_info->type != XR_TYPE_FRAME_BEGIN_INFO,
64             XR_ERROR_VALIDATION_FAILURE, "XrFrameBeginInfo type invalid");
65   RETURN_IF(frame_begin_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
66             "XrFrameBeginInfo next is not nullptr");
67   return g_test_helper.BeginFrame();
68 }
69 
xrBeginSession(XrSession session,const XrSessionBeginInfo * begin_info)70 XrResult xrBeginSession(XrSession session,
71                         const XrSessionBeginInfo* begin_info) {
72   DVLOG(2) << __FUNCTION__;
73   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
74   RETURN_IF(begin_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
75             "XrSessionBeginInfo is nullptr");
76   RETURN_IF(begin_info->type != XR_TYPE_SESSION_BEGIN_INFO,
77             XR_ERROR_VALIDATION_FAILURE, "XrSessionBeginInfo type invalid");
78   RETURN_IF(begin_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
79             "XrSessionBeginInfo next is not nullptr");
80   RETURN_IF(begin_info->primaryViewConfigurationType !=
81                 OpenXrTestHelper::kViewConfigurationType,
82             XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED,
83             "XrSessionBeginInfo primaryViewConfigurationType invalid");
84 
85   RETURN_IF_XR_FAILED(g_test_helper.BeginSession());
86 
87   return XR_SUCCESS;
88 }
89 
xrCreateAction(XrActionSet action_set,const XrActionCreateInfo * create_info,XrAction * action)90 XrResult xrCreateAction(XrActionSet action_set,
91                         const XrActionCreateInfo* create_info,
92                         XrAction* action) {
93   DVLOG(2) << __FUNCTION__;
94   RETURN_IF(create_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
95             "XrActionCreateInfo is nullptr");
96   RETURN_IF_XR_FAILED(
97       g_test_helper.CreateAction(action_set, *create_info, action));
98 
99   return XR_SUCCESS;
100 }
101 
xrCreateActionSet(XrInstance instance,const XrActionSetCreateInfo * create_info,XrActionSet * action_set)102 XrResult xrCreateActionSet(XrInstance instance,
103                            const XrActionSetCreateInfo* create_info,
104                            XrActionSet* action_set) {
105   DVLOG(2) << __FUNCTION__;
106   RETURN_IF_XR_FAILED(g_test_helper.ValidateInstance(instance));
107   RETURN_IF(create_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
108             "XrActionSetCreateInfo is nullptr");
109   RETURN_IF_XR_FAILED(g_test_helper.ValidateActionSetCreateInfo(*create_info));
110   RETURN_IF(action_set == nullptr, XR_ERROR_VALIDATION_FAILURE,
111             "XrActionSet is nullptr");
112   *action_set = g_test_helper.CreateActionSet(*create_info);
113 
114   return XR_SUCCESS;
115 }
116 
xrCreateActionSpace(XrSession session,const XrActionSpaceCreateInfo * create_info,XrSpace * space)117 XrResult xrCreateActionSpace(XrSession session,
118                              const XrActionSpaceCreateInfo* create_info,
119                              XrSpace* space) {
120   DVLOG(2) << __FUNCTION__;
121   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
122   RETURN_IF(create_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
123             "XrActionSpaceCreateInfo is nullptr");
124   RETURN_IF(space == nullptr, XR_ERROR_VALIDATION_FAILURE,
125             "XrSpace is nullptr");
126   RETURN_IF_XR_FAILED(g_test_helper.CreateActionSpace(*create_info, space));
127 
128   return XR_SUCCESS;
129 }
130 
xrCreateInstance(const XrInstanceCreateInfo * create_info,XrInstance * instance)131 XrResult xrCreateInstance(const XrInstanceCreateInfo* create_info,
132                           XrInstance* instance) {
133   DVLOG(2) << __FUNCTION__;
134 
135   RETURN_IF(create_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
136             "XrInstanceCreateInfo is nullptr");
137   RETURN_IF(create_info->applicationInfo.apiVersion != XR_CURRENT_API_VERSION,
138             XR_ERROR_API_VERSION_UNSUPPORTED, "apiVersion unsupported");
139 
140   RETURN_IF(create_info->type != XR_TYPE_INSTANCE_CREATE_INFO,
141             XR_ERROR_VALIDATION_FAILURE, "XrInstanceCreateInfo type invalid");
142 
143   RETURN_IF(create_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
144             "XrInstanceCreateInfo next is not nullptr");
145 
146   RETURN_IF(create_info->createFlags != 0, XR_ERROR_VALIDATION_FAILURE,
147             "XrInstanceCreateInfo createFlags is not 0");
148 
149   RETURN_IF(
150       create_info->enabledApiLayerCount != 0 ||
151           create_info->enabledApiLayerNames != nullptr,
152       XR_ERROR_VALIDATION_FAILURE,
153       "XrInstanceCreateInfo ApiLayer is not supported by this version of test");
154 
155   for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
156     bool valid_extension = false;
157     for (size_t j = 0; j < OpenXrTestHelper::kNumExtensionsSupported; j++) {
158       if (strcmp(create_info->enabledExtensionNames[i],
159                  OpenXrTestHelper::kExtensions[j]) == 0) {
160         valid_extension = true;
161         break;
162       }
163     }
164 
165     RETURN_IF_FALSE(valid_extension, XR_ERROR_VALIDATION_FAILURE,
166                     "enabledExtensionNames contains invalid extensions");
167   }
168 
169   RETURN_IF(instance == nullptr, XR_ERROR_VALIDATION_FAILURE,
170             "XrInstance is nullptr");
171   *instance = g_test_helper.CreateInstance();
172 
173   return XR_SUCCESS;
174 }
175 
xrCreateReferenceSpace(XrSession session,const XrReferenceSpaceCreateInfo * create_info,XrSpace * space)176 XrResult xrCreateReferenceSpace(XrSession session,
177                                 const XrReferenceSpaceCreateInfo* create_info,
178                                 XrSpace* space) {
179   DVLOG(2) << __FUNCTION__;
180   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
181   RETURN_IF(create_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
182             "XrReferenceSpaceCreateInfo is nullptr");
183   RETURN_IF(create_info->type != XR_TYPE_REFERENCE_SPACE_CREATE_INFO,
184             XR_ERROR_VALIDATION_FAILURE,
185             "XrReferenceSpaceCreateInfo type invalid");
186   RETURN_IF(create_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
187             "XrReferenceSpaceCreateInfo next is not nullptr");
188   RETURN_IF(
189       create_info->referenceSpaceType != XR_REFERENCE_SPACE_TYPE_LOCAL &&
190           create_info->referenceSpaceType != XR_REFERENCE_SPACE_TYPE_VIEW &&
191           create_info->referenceSpaceType != XR_REFERENCE_SPACE_TYPE_STAGE &&
192           create_info->referenceSpaceType !=
193               XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT,
194       XR_ERROR_REFERENCE_SPACE_UNSUPPORTED,
195       "XrReferenceSpaceCreateInfo referenceSpaceType invalid");
196   RETURN_IF_XR_FAILED(g_test_helper.ValidateXrPosefIsIdentity(
197       create_info->poseInReferenceSpace));
198   RETURN_IF(space == nullptr, XR_ERROR_VALIDATION_FAILURE,
199             "XrSpace is nullptr");
200   *space = g_test_helper.CreateReferenceSpace(create_info->referenceSpaceType);
201 
202   return XR_SUCCESS;
203 }
204 
xrCreateSession(XrInstance instance,const XrSessionCreateInfo * create_info,XrSession * session)205 XrResult xrCreateSession(XrInstance instance,
206                          const XrSessionCreateInfo* create_info,
207                          XrSession* session) {
208   DVLOG(2) << __FUNCTION__;
209   RETURN_IF_XR_FAILED(g_test_helper.ValidateInstance(instance));
210   RETURN_IF(create_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
211             "XrSessionCreateInfo is nullptr");
212   RETURN_IF(create_info->type != XR_TYPE_SESSION_CREATE_INFO,
213             XR_ERROR_VALIDATION_FAILURE, "XrSessionCreateInfo type invalid");
214   RETURN_IF(create_info->createFlags != 0, XR_ERROR_VALIDATION_FAILURE,
215             "XrSessionCreateInfo createFlags is not 0");
216   RETURN_IF_XR_FAILED(g_test_helper.ValidateSystemId(create_info->systemId));
217 
218   const XrGraphicsBindingD3D11KHR* binding =
219       static_cast<const XrGraphicsBindingD3D11KHR*>(create_info->next);
220   RETURN_IF(binding->type != XR_TYPE_GRAPHICS_BINDING_D3D11_KHR,
221             XR_ERROR_VALIDATION_FAILURE,
222             "XrGraphicsBindingD3D11KHR type invalid");
223   RETURN_IF(binding->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
224             "XrGraphicsBindingD3D11KHR next is not nullptr");
225   RETURN_IF(binding->device == nullptr, XR_ERROR_VALIDATION_FAILURE,
226             "D3D11Device is nullptr");
227 
228   g_test_helper.SetD3DDevice(binding->device);
229   RETURN_IF(session == nullptr, XR_ERROR_VALIDATION_FAILURE,
230             "XrSession is nullptr");
231   RETURN_IF_XR_FAILED(g_test_helper.GetSession(session));
232 
233   return XR_SUCCESS;
234 }
235 
xrCreateSwapchain(XrSession session,const XrSwapchainCreateInfo * create_info,XrSwapchain * swapchain)236 XrResult xrCreateSwapchain(XrSession session,
237                            const XrSwapchainCreateInfo* create_info,
238                            XrSwapchain* swapchain) {
239   DVLOG(2) << __FUNCTION__;
240   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
241   RETURN_IF(create_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
242             "XrSwapchainCreateInfo is nullptr");
243   RETURN_IF(create_info->type != XR_TYPE_SWAPCHAIN_CREATE_INFO,
244             XR_ERROR_VALIDATION_FAILURE, "XrSwapchainCreateInfo type invalid");
245   RETURN_IF(create_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
246             "XrSwapchainCreateInfo next is not nullptr");
247   RETURN_IF(create_info->createFlags != 0, XR_ERROR_VALIDATION_FAILURE,
248             "XrSwapchainCreateInfo createFlags is not 0");
249   RETURN_IF(create_info->usageFlags != XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT,
250             XR_ERROR_VALIDATION_FAILURE,
251             "XrSwapchainCreateInfo usageFlags is not "
252             "XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT");
253   RETURN_IF(create_info->format != DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
254             XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED,
255             "XrSwapchainCreateInfo format unsupported");
256   RETURN_IF(create_info->sampleCount != OpenXrTestHelper::kSwapCount,
257             XR_ERROR_VALIDATION_FAILURE,
258             "XrSwapchainCreateInfo sampleCount invalid");
259   RETURN_IF(create_info->width != OpenXrTestHelper::kDimension * 2,
260             XR_ERROR_VALIDATION_FAILURE,
261             "XrSwapchainCreateInfo width is not dimension * 2");
262   RETURN_IF(create_info->height != OpenXrTestHelper::kDimension,
263             XR_ERROR_VALIDATION_FAILURE,
264             "XrSwapchainCreateInfo height is not dimension");
265   RETURN_IF(create_info->faceCount != 1, XR_ERROR_VALIDATION_FAILURE,
266             "XrSwapchainCreateInfo faceCount is not 1");
267   RETURN_IF(create_info->arraySize != 1, XR_ERROR_VALIDATION_FAILURE,
268             "XrSwapchainCreateInfo arraySize invalid");
269   RETURN_IF(create_info->mipCount != 1, XR_ERROR_VALIDATION_FAILURE,
270             "XrSwapchainCreateInfo mipCount is not 1");
271 
272   RETURN_IF(swapchain == nullptr, XR_ERROR_VALIDATION_FAILURE,
273             "XrSwapchain is nullptr");
274   *swapchain = g_test_helper.GetSwapchain();
275 
276   return XR_SUCCESS;
277 }
278 
xrDestroyActionSet(XrActionSet action_set)279 XrResult xrDestroyActionSet(XrActionSet action_set) {
280   DVLOG(2) << __FUNCTION__;
281   RETURN_IF_XR_FAILED(g_test_helper.ValidateActionSet(action_set));
282   return XR_SUCCESS;
283 }
284 
xrDestroyInstance(XrInstance instance)285 XrResult xrDestroyInstance(XrInstance instance) {
286   DVLOG(2) << __FUNCTION__;
287   RETURN_IF_XR_FAILED(g_test_helper.ValidateInstance(instance));
288   g_test_helper.Reset();
289   return XR_SUCCESS;
290 }
291 
xrDestroySession(XrSession session)292 XrResult xrDestroySession(XrSession session) {
293   DVLOG(2) << __FUNCTION__;
294   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
295   return XR_SUCCESS;
296 }
297 
xrDestroySpace(XrSpace space)298 XrResult xrDestroySpace(XrSpace space) {
299   DVLOG(2) << __FUNCTION__;
300   RETURN_IF_XR_FAILED(g_test_helper.ValidateSpace(space));
301 
302   return XR_SUCCESS;
303 }
304 
xrEndFrame(XrSession session,const XrFrameEndInfo * frame_end_info)305 XrResult xrEndFrame(XrSession session, const XrFrameEndInfo* frame_end_info) {
306   DVLOG(2) << __FUNCTION__;
307   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
308   RETURN_IF(frame_end_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
309             "XrFrameEndInfo is nullptr");
310   RETURN_IF(frame_end_info->type != XR_TYPE_FRAME_END_INFO,
311             XR_ERROR_VALIDATION_FAILURE, "XrFrameEndInfo type invalid");
312   RETURN_IF(frame_end_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
313             "XrFrameEndInfo next is not nullptr");
314   RETURN_IF_XR_FAILED(
315       g_test_helper.ValidatePredictedDisplayTime(frame_end_info->displayTime));
316   RETURN_IF(frame_end_info->environmentBlendMode !=
317                 OpenXrTestHelper::kEnvironmentBlendMode,
318             XR_ERROR_VALIDATION_FAILURE,
319             "XrFrameEndInfo environmentBlendMode invalid");
320   RETURN_IF(frame_end_info->layerCount != 1, XR_ERROR_VALIDATION_FAILURE,
321             "XrFrameEndInfo layerCount invalid");
322   RETURN_IF(frame_end_info->layers == nullptr, XR_ERROR_LAYER_INVALID,
323             "XrFrameEndInfo has nullptr layers");
324 
325   for (uint32_t i = 0; i < frame_end_info->layerCount; i++) {
326     const XrCompositionLayerProjection* multi_projection_layer_ptr =
327         reinterpret_cast<const XrCompositionLayerProjection*>(
328             frame_end_info->layers[i]);
329     RETURN_IF_XR_FAILED(g_test_helper.ValidateXrCompositionLayerProjection(
330         *multi_projection_layer_ptr));
331   }
332 
333   RETURN_IF_XR_FAILED(g_test_helper.EndFrame());
334   g_test_helper.OnPresentedFrame();
335   return XR_SUCCESS;
336 }
337 
xrEndSession(XrSession session)338 XrResult xrEndSession(XrSession session) {
339   DVLOG(2) << __FUNCTION__;
340   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
341   RETURN_IF_XR_FAILED(g_test_helper.EndSession());
342 
343   return XR_SUCCESS;
344 }
345 
xrEnumerateEnvironmentBlendModes(XrInstance instance,XrSystemId system_id,XrViewConfigurationType view_configuration_type,uint32_t environment_blend_mode_capacity_input,uint32_t * environment_blend_mode_count_output,XrEnvironmentBlendMode * environment_blend_modes)346 XrResult xrEnumerateEnvironmentBlendModes(
347     XrInstance instance,
348     XrSystemId system_id,
349     XrViewConfigurationType view_configuration_type,
350     uint32_t environment_blend_mode_capacity_input,
351     uint32_t* environment_blend_mode_count_output,
352     XrEnvironmentBlendMode* environment_blend_modes) {
353   DVLOG(2) << __FUNCTION__;
354   RETURN_IF_XR_FAILED(g_test_helper.ValidateInstance(instance));
355   RETURN_IF_XR_FAILED(g_test_helper.ValidateSystemId(system_id));
356   RETURN_IF(view_configuration_type != OpenXrTestHelper::kViewConfigurationType,
357             XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED,
358             "xrEnumerateEnvironmentBlendModes viewConfigurationType invalid");
359 
360   RETURN_IF(environment_blend_mode_count_output == nullptr,
361             XR_ERROR_VALIDATION_FAILURE,
362             "environment_blend_mode_count_output is nullptr");
363   *environment_blend_mode_count_output = 1;
364   if (environment_blend_mode_capacity_input == 0) {
365     return XR_SUCCESS;
366   }
367 
368   RETURN_IF(environment_blend_mode_capacity_input != 1,
369             XR_ERROR_VALIDATION_FAILURE,
370             "environment_blend_mode_capacity_input is neither 0 or 1");
371   RETURN_IF(environment_blend_modes == nullptr, XR_ERROR_VALIDATION_FAILURE,
372             "XrEnvironmentBlendMode is nullptr");
373   *environment_blend_modes = OpenXrTestHelper::kEnvironmentBlendMode;
374 
375   return XR_SUCCESS;
376 }
377 
378 // Even thought xrEnumerateInstanceExtensionProperties is not directly called
379 // in our implementation, it is used inside loader so this function mock is
380 // needed
xrEnumerateInstanceExtensionProperties(const char * layer_name,uint32_t property_capacity_input,uint32_t * property_count_output,XrExtensionProperties * properties)381 XrResult xrEnumerateInstanceExtensionProperties(
382     const char* layer_name,
383     uint32_t property_capacity_input,
384     uint32_t* property_count_output,
385     XrExtensionProperties* properties) {
386   DVLOG(2) << __FUNCTION__;
387 
388   RETURN_IF(
389       property_capacity_input < OpenXrTestHelper::kNumExtensionsSupported &&
390           property_capacity_input != 0,
391       XR_ERROR_SIZE_INSUFFICIENT, "XrExtensionProperties array is too small");
392 
393   RETURN_IF(property_count_output == nullptr, XR_ERROR_VALIDATION_FAILURE,
394             "property_count_output is nullptr");
395   *property_count_output = OpenXrTestHelper::kNumExtensionsSupported;
396   if (property_capacity_input == 0) {
397     return XR_SUCCESS;
398   }
399 
400   RETURN_IF(
401       property_capacity_input != OpenXrTestHelper::kNumExtensionsSupported,
402       XR_ERROR_VALIDATION_FAILURE,
403       "property_capacity_input is neither 0 or kNumExtensionsSupported");
404   RETURN_IF(properties == nullptr, XR_ERROR_VALIDATION_FAILURE,
405             "XrExtensionProperties is nullptr");
406   for (uint32_t i = 0; i < OpenXrTestHelper::kNumExtensionsSupported; i++) {
407     properties[i].type = XR_TYPE_EXTENSION_PROPERTIES;
408     errno_t error = strcpy_s(properties[i].extensionName,
409                              base::size(properties[i].extensionName),
410                              OpenXrTestHelper::kExtensions[i]);
411     DCHECK(error == 0);
412     properties[i].extensionVersion = 1;
413   }
414 
415   return XR_SUCCESS;
416 }
417 
xrEnumerateViewConfigurationViews(XrInstance instance,XrSystemId system_id,XrViewConfigurationType view_configuration_type,uint32_t view_capacity_input,uint32_t * view_count_output,XrViewConfigurationView * views)418 XrResult xrEnumerateViewConfigurationViews(
419     XrInstance instance,
420     XrSystemId system_id,
421     XrViewConfigurationType view_configuration_type,
422     uint32_t view_capacity_input,
423     uint32_t* view_count_output,
424     XrViewConfigurationView* views) {
425   DVLOG(2) << __FUNCTION__;
426   RETURN_IF_XR_FAILED(g_test_helper.ValidateInstance(instance));
427   RETURN_IF_XR_FAILED(g_test_helper.ValidateSystemId(system_id));
428   RETURN_IF(view_configuration_type != OpenXrTestHelper::kViewConfigurationType,
429             XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED,
430             "xrEnumerateViewConfigurationViews viewConfigurationType invalid");
431   RETURN_IF(view_count_output == nullptr, XR_ERROR_VALIDATION_FAILURE,
432             "view_count_output is nullptr");
433   *view_count_output = OpenXrTestHelper::kNumViews;
434   if (view_capacity_input == 0) {
435     return XR_SUCCESS;
436   }
437 
438   RETURN_IF(view_capacity_input != OpenXrTestHelper::kNumViews,
439             XR_ERROR_VALIDATION_FAILURE,
440             "view_capacity_input is neither 0 or kNumViews");
441   RETURN_IF(views == nullptr, XR_ERROR_VALIDATION_FAILURE,
442             "XrViewConfigurationView is nullptr");
443   views[0] = OpenXrTestHelper::kViewConfigurationViews[0];
444   views[1] = OpenXrTestHelper::kViewConfigurationViews[1];
445 
446   return XR_SUCCESS;
447 }
448 
xrEnumerateSwapchainImages(XrSwapchain swapchain,uint32_t image_capacity_input,uint32_t * image_count_output,XrSwapchainImageBaseHeader * images)449 XrResult xrEnumerateSwapchainImages(XrSwapchain swapchain,
450                                     uint32_t image_capacity_input,
451                                     uint32_t* image_count_output,
452                                     XrSwapchainImageBaseHeader* images) {
453   DVLOG(2) << __FUNCTION__;
454   RETURN_IF_XR_FAILED(g_test_helper.ValidateSwapchain(swapchain));
455   RETURN_IF(image_capacity_input != OpenXrTestHelper::kMinSwapchainBuffering &&
456                 image_capacity_input != 0,
457             XR_ERROR_SIZE_INSUFFICIENT,
458             "xrEnumerateSwapchainImages does not equal length returned by "
459             "xrCreateSwapchain");
460 
461   RETURN_IF(image_count_output == nullptr, XR_ERROR_VALIDATION_FAILURE,
462             "image_capacity_input is nullptr");
463   *image_count_output = OpenXrTestHelper::kMinSwapchainBuffering;
464   if (image_capacity_input == 0) {
465     return XR_SUCCESS;
466   }
467 
468   RETURN_IF(image_capacity_input != OpenXrTestHelper::kMinSwapchainBuffering,
469             XR_ERROR_VALIDATION_FAILURE,
470             "image_capacity_input is neither 0 or kMinSwapchainBuffering");
471   RETURN_IF(images == nullptr, XR_ERROR_VALIDATION_FAILURE,
472             "XrSwapchainImageBaseHeader is nullptr");
473   const std::vector<Microsoft::WRL::ComPtr<ID3D11Texture2D>>& textures =
474       g_test_helper.GetSwapchainTextures();
475   DCHECK(textures.size() == image_capacity_input);
476 
477   for (uint32_t i = 0; i < image_capacity_input; i++) {
478     XrSwapchainImageD3D11KHR& image =
479         reinterpret_cast<XrSwapchainImageD3D11KHR*>(images)[i];
480 
481     RETURN_IF(image.type != XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR,
482               XR_ERROR_VALIDATION_FAILURE,
483               "XrSwapchainImageD3D11KHR type invalid");
484     RETURN_IF(image.next != nullptr, XR_ERROR_VALIDATION_FAILURE,
485               "XrSwapchainImageD3D11KHR next is not nullptr");
486 
487     image.texture = textures[i].Get();
488   }
489 
490   return XR_SUCCESS;
491 }
492 
xrGetD3D11GraphicsRequirementsKHR(XrInstance instance,XrSystemId system_id,XrGraphicsRequirementsD3D11KHR * graphics_requirements)493 XrResult xrGetD3D11GraphicsRequirementsKHR(
494     XrInstance instance,
495     XrSystemId system_id,
496     XrGraphicsRequirementsD3D11KHR* graphics_requirements) {
497   DVLOG(2) << __FUNCTION__;
498   RETURN_IF_XR_FAILED(g_test_helper.ValidateInstance(instance));
499   RETURN_IF_XR_FAILED(g_test_helper.ValidateSystemId(system_id));
500   RETURN_IF(graphics_requirements == nullptr, XR_ERROR_VALIDATION_FAILURE,
501             "XrGraphicsRequirementsD3D11KHR is nullptr");
502   RETURN_IF(
503       graphics_requirements->type != XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR,
504       XR_ERROR_VALIDATION_FAILURE,
505       "XrGraphicsRequirementsD3D11KHR type invalid");
506   RETURN_IF(graphics_requirements->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
507             "XrGraphicsRequirementsD3D11KHR next is not nullptr");
508 
509   Microsoft::WRL::ComPtr<IDXGIFactory1> dxgi_factory;
510   Microsoft::WRL::ComPtr<IDXGIAdapter> adapter;
511   HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgi_factory));
512   DCHECK(SUCCEEDED(hr));
513   if (SUCCEEDED(dxgi_factory->EnumAdapters(0, &adapter))) {
514     DXGI_ADAPTER_DESC desc;
515     adapter->GetDesc(&desc);
516     graphics_requirements->adapterLuid = desc.AdapterLuid;
517 
518     // Require D3D11.1 to support shared NT handles.
519     graphics_requirements->minFeatureLevel = D3D_FEATURE_LEVEL_11_1;
520 
521     return XR_SUCCESS;
522   }
523 
524   RETURN_IF_FALSE(false, XR_ERROR_VALIDATION_FAILURE,
525                   "Unable to create query DXGI Adapter");
526 }
527 
xrGetActionStateFloat(XrSession session,const XrActionStateGetInfo * get_info,XrActionStateFloat * state)528 XrResult xrGetActionStateFloat(XrSession session,
529                                const XrActionStateGetInfo* get_info,
530                                XrActionStateFloat* state) {
531   DVLOG(2) << __FUNCTION__;
532   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
533   RETURN_IF(get_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
534             "XrActionStateGetInfo is nullptr");
535   RETURN_IF(get_info->type != XR_TYPE_ACTION_STATE_GET_INFO,
536             XR_ERROR_VALIDATION_FAILURE,
537             "xrGetActionStateFloat has wrong type");
538   RETURN_IF(get_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
539             "xrGetActionStateFloat next is not nullptr");
540   RETURN_IF_XR_FAILED(g_test_helper.ValidateAction(get_info->action));
541   RETURN_IF(get_info->subactionPath != XR_NULL_PATH,
542             XR_ERROR_VALIDATION_FAILURE,
543             "xrGetActionStateFloat has subactionPath != nullptr which is not "
544             "supported by current version of test.");
545   RETURN_IF_XR_FAILED(
546       g_test_helper.GetActionStateFloat(get_info->action, state));
547 
548   return XR_SUCCESS;
549 }
550 
xrGetActionStateBoolean(XrSession session,const XrActionStateGetInfo * get_info,XrActionStateBoolean * state)551 XrResult xrGetActionStateBoolean(XrSession session,
552                                  const XrActionStateGetInfo* get_info,
553                                  XrActionStateBoolean* state) {
554   DVLOG(2) << __FUNCTION__;
555   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
556   RETURN_IF(get_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
557             "XrActionStateGetInfo is nullptr");
558   RETURN_IF(get_info->type != XR_TYPE_ACTION_STATE_GET_INFO,
559             XR_ERROR_VALIDATION_FAILURE,
560             "xrGetActionStateBoolean get_info has wrong type");
561   RETURN_IF(get_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
562             "xrGetActionStateBoolean next is not nullptr");
563   RETURN_IF_XR_FAILED(g_test_helper.ValidateAction(get_info->action));
564   RETURN_IF(get_info->subactionPath != XR_NULL_PATH,
565             XR_ERROR_VALIDATION_FAILURE,
566             "xrGetActionStateBoolean has subactionPath != nullptr which is not "
567             "supported by current version of test.");
568   RETURN_IF_XR_FAILED(
569       g_test_helper.GetActionStateBoolean(get_info->action, state));
570 
571   return XR_SUCCESS;
572 }
573 
xrGetActionStateVector2f(XrSession session,const XrActionStateGetInfo * get_info,XrActionStateVector2f * state)574 XrResult xrGetActionStateVector2f(XrSession session,
575                                   const XrActionStateGetInfo* get_info,
576                                   XrActionStateVector2f* state) {
577   DVLOG(2) << __FUNCTION__;
578   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
579   RETURN_IF(get_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
580             "XrActionStateGetInfo is nullptr");
581   RETURN_IF(get_info->type != XR_TYPE_ACTION_STATE_GET_INFO,
582             XR_ERROR_VALIDATION_FAILURE,
583             "xrGetActionStateVector2f get_info has wrong type");
584   RETURN_IF(get_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
585             "xrGetActionStateVector2f next is not nullptr");
586   RETURN_IF_XR_FAILED(g_test_helper.ValidateAction(get_info->action));
587   RETURN_IF(
588       get_info->subactionPath != XR_NULL_PATH, XR_ERROR_VALIDATION_FAILURE,
589       "xrGetActionStateVector2f has subactionPath != nullptr which is not "
590       "supported by current version of test.");
591   RETURN_IF_XR_FAILED(
592       g_test_helper.GetActionStateVector2f(get_info->action, state));
593 
594   return XR_SUCCESS;
595 }
596 
xrGetActionStatePose(XrSession session,const XrActionStateGetInfo * get_info,XrActionStatePose * state)597 XrResult xrGetActionStatePose(XrSession session,
598                               const XrActionStateGetInfo* get_info,
599                               XrActionStatePose* state) {
600   DVLOG(2) << __FUNCTION__;
601   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
602   RETURN_IF(get_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
603             "XrActionStateGetInfo is nullptr");
604   RETURN_IF(get_info->type != XR_TYPE_ACTION_STATE_GET_INFO,
605             XR_ERROR_VALIDATION_FAILURE,
606             "xrGetActionStatePose get_info has wrong type");
607   RETURN_IF(get_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
608             "xrGetActionStatePose next is not nullptr");
609   RETURN_IF_XR_FAILED(g_test_helper.ValidateAction(get_info->action));
610   RETURN_IF(get_info->subactionPath != XR_NULL_PATH,
611             XR_ERROR_VALIDATION_FAILURE,
612             "xrGetActionStatePose has subactionPath != nullptr which is not "
613             "supported by current version of test.");
614   RETURN_IF_XR_FAILED(
615       g_test_helper.GetActionStatePose(get_info->action, state));
616 
617   return XR_SUCCESS;
618 }
619 
xrGetCurrentInteractionProfile(XrSession session,XrPath top_level_user_path,XrInteractionProfileState * interaction_profile)620 XrResult xrGetCurrentInteractionProfile(
621     XrSession session,
622     XrPath top_level_user_path,
623     XrInteractionProfileState* interaction_profile) {
624   DVLOG(1) << __FUNCTION__;
625   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
626   RETURN_IF(
627       g_test_helper.AttachedActionSetsSize() == 0,
628       XR_ERROR_ACTIONSET_NOT_ATTACHED,
629       "xrGetCurrentInteractionProfile action sets have not been attached yet");
630   RETURN_IF_XR_FAILED(g_test_helper.ValidatePath(top_level_user_path));
631   RETURN_IF(interaction_profile == nullptr, XR_ERROR_VALIDATION_FAILURE,
632             "XrInteractionProfileState is nullptr");
633   RETURN_IF(interaction_profile->type != XR_TYPE_INTERACTION_PROFILE_STATE,
634             XR_ERROR_VALIDATION_FAILURE,
635             "xrGetCurrentInteractionProfile type is not "
636             "XR_TYPE_INTERACTION_PROFILE_STATE");
637   RETURN_IF(interaction_profile->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
638             "xrGetCurrentInteractionProfile next is not "
639             "nullptr");
640   interaction_profile->interactionProfile =
641       g_test_helper.GetCurrentInteractionProfile();
642   return XR_SUCCESS;
643 }
644 
xrGetReferenceSpaceBoundsRect(XrSession session,XrReferenceSpaceType refernece_space_type,XrExtent2Df * bounds)645 XrResult xrGetReferenceSpaceBoundsRect(
646     XrSession session,
647     XrReferenceSpaceType refernece_space_type,
648     XrExtent2Df* bounds) {
649   DVLOG(2) << __FUNCTION__;
650   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
651   RETURN_IF(refernece_space_type != XR_REFERENCE_SPACE_TYPE_STAGE,
652             XR_ERROR_REFERENCE_SPACE_UNSUPPORTED,
653             "xrGetReferenceSpaceBoundsRect type is not stage");
654   RETURN_IF(bounds == nullptr, XR_ERROR_VALIDATION_FAILURE,
655             "XrExtent2Df is nullptr");
656   bounds->width = 0;
657   bounds->height = 0;
658   return XR_SUCCESS;
659 }
660 
xrGetSystem(XrInstance instance,const XrSystemGetInfo * get_info,XrSystemId * system_id)661 XrResult xrGetSystem(XrInstance instance,
662                      const XrSystemGetInfo* get_info,
663                      XrSystemId* system_id) {
664   DVLOG(2) << __FUNCTION__;
665   RETURN_IF_XR_FAILED(g_test_helper.ValidateInstance(instance));
666   RETURN_IF(get_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
667             "XrSystemGetInfo is nullptr");
668   RETURN_IF(get_info->type != XR_TYPE_SYSTEM_GET_INFO,
669             XR_ERROR_VALIDATION_FAILURE, "XrSystemGetInfo type invalid");
670   RETURN_IF(get_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
671             "XrSystemGetInfo next is not nullptr");
672   RETURN_IF(get_info->formFactor != XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY,
673             XR_ERROR_VALIDATION_FAILURE, "XrSystemGetInfo formFactor invalid");
674 
675   RETURN_IF(system_id == nullptr, XR_ERROR_VALIDATION_FAILURE,
676             "XrSystemId is nullptr");
677   *system_id = g_test_helper.GetSystemId();
678 
679   return XR_SUCCESS;
680 }
681 
xrLocateSpace(XrSpace space,XrSpace base_space,XrTime time,XrSpaceLocation * location)682 XrResult xrLocateSpace(XrSpace space,
683                        XrSpace base_space,
684                        XrTime time,
685                        XrSpaceLocation* location) {
686   DVLOG(2) << __FUNCTION__;
687   RETURN_IF_XR_FAILED(g_test_helper.ValidateSpace(space));
688   RETURN_IF_XR_FAILED(g_test_helper.ValidateSpace(base_space));
689   RETURN_IF_XR_FAILED(g_test_helper.ValidatePredictedDisplayTime(time));
690 
691   RETURN_IF(location == nullptr, XR_ERROR_VALIDATION_FAILURE,
692             "XrSpaceLocation is nullptr");
693   g_test_helper.LocateSpace(space, &(location->pose));
694 
695   location->locationFlags = XR_SPACE_LOCATION_ORIENTATION_VALID_BIT |
696                             XR_SPACE_LOCATION_POSITION_VALID_BIT |
697                             XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT |
698                             XR_SPACE_LOCATION_POSITION_TRACKED_BIT;
699 
700   return XR_SUCCESS;
701 }
702 
xrLocateViews(XrSession session,const XrViewLocateInfo * view_locate_info,XrViewState * view_state,uint32_t view_capacity_input,uint32_t * view_count_output,XrView * views)703 XrResult xrLocateViews(XrSession session,
704                        const XrViewLocateInfo* view_locate_info,
705                        XrViewState* view_state,
706                        uint32_t view_capacity_input,
707                        uint32_t* view_count_output,
708                        XrView* views) {
709   DVLOG(2) << __FUNCTION__;
710   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
711   RETURN_IF(view_locate_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
712             "XrViewLocateInfo is nullptr");
713   RETURN_IF(view_locate_info->type != XR_TYPE_VIEW_LOCATE_INFO,
714             XR_ERROR_VALIDATION_FAILURE,
715             "xrLocateViews view_locate_info type invalid");
716   RETURN_IF(view_locate_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
717             "XrViewLocateInfo next is not nullptr");
718   RETURN_IF(view_locate_info->viewConfigurationType !=
719                 OpenXrTestHelper::kViewConfigurationType,
720             XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED,
721             "XrViewLocateInfo viewConfigurationType invalid");
722   RETURN_IF_XR_FAILED(g_test_helper.ValidatePredictedDisplayTime(
723       view_locate_info->displayTime));
724   RETURN_IF_XR_FAILED(g_test_helper.ValidateSpace(view_locate_info->space));
725   RETURN_IF(view_state == nullptr, XR_ERROR_VALIDATION_FAILURE,
726             "XrViewState is nullptr");
727   RETURN_IF(view_count_output == nullptr, XR_ERROR_VALIDATION_FAILURE,
728             "view_count_output is nullptr");
729   *view_count_output = OpenXrTestHelper::kViewCount;
730   if (view_capacity_input == 0) {
731     return XR_SUCCESS;
732   }
733 
734   RETURN_IF(view_capacity_input != OpenXrTestHelper::kViewCount,
735             XR_ERROR_VALIDATION_FAILURE,
736             "view_capacity_input is neither 0 or OpenXrTestHelper::kViewCount");
737   RETURN_IF_XR_FAILED(g_test_helper.ValidateViews(view_capacity_input, views));
738   RETURN_IF_FALSE(g_test_helper.UpdateViewFOV(views, view_capacity_input),
739                   XR_ERROR_VALIDATION_FAILURE,
740                   "xrLocateViews UpdateViewFOV failed");
741   view_state->viewStateFlags =
742       XR_VIEW_STATE_POSITION_VALID_BIT | XR_VIEW_STATE_ORIENTATION_VALID_BIT;
743 
744   return XR_SUCCESS;
745 }
746 
xrPollEvent(XrInstance instance,XrEventDataBuffer * event_data)747 XrResult xrPollEvent(XrInstance instance, XrEventDataBuffer* event_data) {
748   DVLOG(2) << __FUNCTION__;
749   RETURN_IF_XR_FAILED(g_test_helper.ValidateInstance(instance));
750 
751   return g_test_helper.PollEvent(event_data);
752 }
753 
xrReleaseSwapchainImage(XrSwapchain swapchain,const XrSwapchainImageReleaseInfo * release_info)754 XrResult xrReleaseSwapchainImage(
755     XrSwapchain swapchain,
756     const XrSwapchainImageReleaseInfo* release_info) {
757   DVLOG(2) << __FUNCTION__;
758   RETURN_IF_XR_FAILED(g_test_helper.ValidateSwapchain(swapchain));
759   RETURN_IF(release_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
760             "XrSwapchainImageReleaseInfo is nullptr");
761   RETURN_IF(release_info->type != XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO,
762             XR_ERROR_VALIDATION_FAILURE,
763             "XrSwapchainImageReleaseInfo type invalid");
764   RETURN_IF(release_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
765             "XrSwapchainImageReleaseInfo next is not nullptr");
766 
767   return XR_SUCCESS;
768 }
769 
xrSuggestInteractionProfileBindings(XrInstance instance,const XrInteractionProfileSuggestedBinding * suggested_bindings)770 XrResult xrSuggestInteractionProfileBindings(
771     XrInstance instance,
772     const XrInteractionProfileSuggestedBinding* suggested_bindings) {
773   DVLOG(2) << __FUNCTION__;
774   RETURN_IF_XR_FAILED(g_test_helper.ValidateInstance(instance));
775   RETURN_IF(suggested_bindings == nullptr, XR_ERROR_VALIDATION_FAILURE,
776             "XrInteractionProfileSuggestedBinding is nullptr");
777   RETURN_IF(
778       suggested_bindings->type != XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING,
779       XR_ERROR_VALIDATION_FAILURE,
780       "xrSetInteractionProfileSuggestedBindings type invalid");
781   RETURN_IF(suggested_bindings->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
782             "xrSetInteractionProfileSuggestedBindings next is not nullptr");
783   RETURN_IF_XR_FAILED(
784       g_test_helper.ValidatePath(suggested_bindings->interactionProfile));
785   std::string interaction_profile =
786       g_test_helper.PathToString(suggested_bindings->interactionProfile);
787 
788   RETURN_IF(suggested_bindings->suggestedBindings == nullptr,
789             XR_ERROR_VALIDATION_FAILURE,
790             "XrInteractionProfileSuggestedBinding has nullptr "
791             "XrActionSuggestedBinding");
792   RETURN_IF(g_test_helper.AttachedActionSetsSize() != 0,
793             XR_ERROR_ACTIONSETS_ALREADY_ATTACHED,
794             "xrSuggestInteractionProfileBindings called after "
795             "xrAttachSessionActionSets");
796   for (uint32_t i = 0; i < suggested_bindings->countSuggestedBindings; i++) {
797     XrActionSuggestedBinding suggestedBinding =
798         suggested_bindings->suggestedBindings[i];
799     RETURN_IF_XR_FAILED(g_test_helper.BindActionAndPath(
800         suggested_bindings->interactionProfile, suggestedBinding));
801   }
802 
803   return XR_SUCCESS;
804 }
805 
xrStringToPath(XrInstance instance,const char * path_string,XrPath * path)806 XrResult xrStringToPath(XrInstance instance,
807                         const char* path_string,
808                         XrPath* path) {
809   DVLOG(2) << __FUNCTION__;
810   RETURN_IF_XR_FAILED(g_test_helper.ValidateInstance(instance));
811   RETURN_IF(path == nullptr, XR_ERROR_VALIDATION_FAILURE, "path is nullptr");
812   *path = g_test_helper.GetPath(path_string);
813 
814   return XR_SUCCESS;
815 }
816 
xrPathToString(XrInstance instance,XrPath path,uint32_t buffer_capacity_input,uint32_t * buffer_count_output,char * buffer)817 XrResult xrPathToString(XrInstance instance,
818                         XrPath path,
819                         uint32_t buffer_capacity_input,
820                         uint32_t* buffer_count_output,
821                         char* buffer) {
822   DVLOG(2) << __FUNCTION__;
823   RETURN_IF_XR_FAILED(g_test_helper.ValidateInstance(instance));
824   RETURN_IF_XR_FAILED(g_test_helper.ValidatePath(path));
825 
826   std::string path_string = g_test_helper.PathToString(path);
827   RETURN_IF(buffer_count_output == nullptr, XR_ERROR_VALIDATION_FAILURE,
828             "buffer_count_output is nullptr");
829   // OpenXR spec counts terminating '\0'
830   *buffer_count_output = path_string.size() + 1;
831   if (buffer_capacity_input == 0) {
832     return XR_SUCCESS;
833   }
834 
835   RETURN_IF(
836       buffer_capacity_input <= path_string.size(), XR_ERROR_SIZE_INSUFFICIENT,
837       "xrPathToString inputsize is not large enough to hold the output string");
838   errno_t error = strcpy_s(buffer, *buffer_count_output, path_string.data());
839   DCHECK(error == 0);
840 
841   return XR_SUCCESS;
842 }
843 
xrSyncActions(XrSession session,const XrActionsSyncInfo * sync_info)844 XrResult xrSyncActions(XrSession session, const XrActionsSyncInfo* sync_info) {
845   DVLOG(2) << __FUNCTION__;
846   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
847   RETURN_IF_FALSE(g_test_helper.UpdateData(), XR_ERROR_VALIDATION_FAILURE,
848                   "xrSyncActionData can't receive data from test");
849   RETURN_IF(sync_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
850             "XrActionsSyncInfo is nullptr");
851   RETURN_IF(sync_info->type != XR_TYPE_ACTIONS_SYNC_INFO,
852             XR_ERROR_VALIDATION_FAILURE, "XrActionsSyncInfo type invalid");
853   RETURN_IF(sync_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
854             "XrActionsSyncInfo next is not nullptr");
855   RETURN_IF(sync_info->activeActionSets == nullptr, XR_ERROR_VALIDATION_FAILURE,
856             "XrActionsSyncInfo activeActionSets is nullptr");
857 
858   for (uint32_t i = 0; i < sync_info->countActiveActionSets; i++) {
859     RETURN_IF(
860         sync_info->activeActionSets[i].subactionPath != XR_NULL_PATH,
861         XR_ERROR_VALIDATION_FAILURE,
862         "xrSyncActionData does not support use of subactionPath for test yet");
863     RETURN_IF_XR_FAILED(
864         g_test_helper.SyncActionData(sync_info->activeActionSets[i].actionSet));
865   }
866 
867   return XR_SUCCESS;
868 }
869 
xrWaitFrame(XrSession session,const XrFrameWaitInfo * frame_wait_info,XrFrameState * frame_state)870 XrResult xrWaitFrame(XrSession session,
871                      const XrFrameWaitInfo* frame_wait_info,
872                      XrFrameState* frame_state) {
873   DVLOG(2) << __FUNCTION__;
874   RETURN_IF_XR_FAILED(g_test_helper.ValidateSession(session));
875   RETURN_IF(frame_wait_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
876             "XrFrameWaitInfo is nullptr");
877   RETURN_IF(frame_wait_info->type != XR_TYPE_FRAME_WAIT_INFO,
878             XR_ERROR_VALIDATION_FAILURE, "frame_wait_info type invalid");
879   RETURN_IF(frame_wait_info->next != nullptr, XR_ERROR_VALIDATION_FAILURE,
880             "XrFrameWaitInfo next is not nullptr");
881   RETURN_IF(frame_state == nullptr, XR_ERROR_VALIDATION_FAILURE,
882             "XrFrameState is nullptr");
883   RETURN_IF(frame_state->type != XR_TYPE_FRAME_STATE,
884             XR_ERROR_VALIDATION_FAILURE, "XR_TYPE_FRAME_STATE type invalid");
885 
886   frame_state->predictedDisplayTime = g_test_helper.NextPredictedDisplayTime();
887 
888   return XR_SUCCESS;
889 }
890 
xrWaitSwapchainImage(XrSwapchain swapchain,const XrSwapchainImageWaitInfo * wait_info)891 XrResult xrWaitSwapchainImage(XrSwapchain swapchain,
892                               const XrSwapchainImageWaitInfo* wait_info) {
893   DVLOG(2) << __FUNCTION__;
894   RETURN_IF_XR_FAILED(g_test_helper.ValidateSwapchain(swapchain));
895   RETURN_IF(wait_info == nullptr, XR_ERROR_VALIDATION_FAILURE,
896             "XrSwapchainImageWaitInfo is nullptr");
897   RETURN_IF(wait_info->type != XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO,
898             XR_ERROR_VALIDATION_FAILURE, "xrWaitSwapchainImage type invalid");
899   RETURN_IF(wait_info->type != XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO,
900             XR_ERROR_VALIDATION_FAILURE,
901             "xrWaitSwapchainImage next is nullptr");
902   RETURN_IF(wait_info->timeout != XR_INFINITE_DURATION,
903             XR_ERROR_VALIDATION_FAILURE,
904             "xrWaitSwapchainImage timeout not XR_INFINITE_DURATION");
905 
906   return XR_SUCCESS;
907 }
908 
909 // Getter for extension methods. Casts the correct function dynamically based on
910 // the method name provided.
911 // Please add new OpenXR APIs below in alphabetical order.
xrGetInstanceProcAddr(XrInstance instance,const char * name,PFN_xrVoidFunction * function)912 XrResult XRAPI_PTR xrGetInstanceProcAddr(XrInstance instance,
913                                          const char* name,
914                                          PFN_xrVoidFunction* function) {
915   if (strcmp(name, "xrAcquireSwapchainImage") == 0) {
916     *function = reinterpret_cast<PFN_xrVoidFunction>(xrAcquireSwapchainImage);
917   } else if (strcmp(name, "xrAttachSessionActionSets") == 0) {
918     *function = reinterpret_cast<PFN_xrVoidFunction>(xrAttachSessionActionSets);
919   } else if (strcmp(name, "xrBeginFrame") == 0) {
920     *function = reinterpret_cast<PFN_xrVoidFunction>(xrBeginFrame);
921   } else if (strcmp(name, "xrBeginSession") == 0) {
922     *function = reinterpret_cast<PFN_xrVoidFunction>(xrBeginSession);
923   } else if (strcmp(name, "xrCreateAction") == 0) {
924     *function = reinterpret_cast<PFN_xrVoidFunction>(xrCreateAction);
925   } else if (strcmp(name, "xrCreateActionSet") == 0) {
926     *function = reinterpret_cast<PFN_xrVoidFunction>(xrCreateActionSet);
927   } else if (strcmp(name, "xrCreateActionSpace") == 0) {
928     *function = reinterpret_cast<PFN_xrVoidFunction>(xrCreateActionSpace);
929   } else if (strcmp(name, "xrCreateInstance") == 0) {
930     *function = reinterpret_cast<PFN_xrVoidFunction>(xrCreateInstance);
931   } else if (strcmp(name, "xrCreateReferenceSpace") == 0) {
932     *function = reinterpret_cast<PFN_xrVoidFunction>(xrCreateReferenceSpace);
933   } else if (strcmp(name, "xrCreateSession") == 0) {
934     *function = reinterpret_cast<PFN_xrVoidFunction>(xrCreateSession);
935   } else if (strcmp(name, "xrCreateSwapchain") == 0) {
936     *function = reinterpret_cast<PFN_xrVoidFunction>(xrCreateSwapchain);
937   } else if (strcmp(name, "xrDestroyActionSet") == 0) {
938     *function = reinterpret_cast<PFN_xrVoidFunction>(xrDestroyActionSet);
939   } else if (strcmp(name, "xrDestroyInstance") == 0) {
940     *function = reinterpret_cast<PFN_xrVoidFunction>(xrDestroyInstance);
941   } else if (strcmp(name, "xrDestroySpace") == 0) {
942     *function = reinterpret_cast<PFN_xrVoidFunction>(xrDestroySpace);
943   } else if (strcmp(name, "xrEndFrame") == 0) {
944     *function = reinterpret_cast<PFN_xrVoidFunction>(xrEndFrame);
945   } else if (strcmp(name, "xrEndSession") == 0) {
946     *function = reinterpret_cast<PFN_xrVoidFunction>(xrEndSession);
947   } else if (strcmp(name, "xrEnumerateEnvironmentBlendModes") == 0) {
948     *function =
949         reinterpret_cast<PFN_xrVoidFunction>(xrEnumerateEnvironmentBlendModes);
950   } else if (strcmp(name, "xrEnumerateInstanceExtensionProperties") == 0) {
951     *function = reinterpret_cast<PFN_xrVoidFunction>(
952         xrEnumerateInstanceExtensionProperties);
953   } else if (strcmp(name, "xrEnumerateSwapchainImages") == 0) {
954     *function =
955         reinterpret_cast<PFN_xrVoidFunction>(xrEnumerateSwapchainImages);
956   } else if (strcmp(name, "xrEnumerateViewConfigurationViews") == 0) {
957     *function =
958         reinterpret_cast<PFN_xrVoidFunction>(xrEnumerateViewConfigurationViews);
959   } else if (strcmp(name, "xrGetD3D11GraphicsRequirementsKHR") == 0) {
960     *function =
961         reinterpret_cast<PFN_xrVoidFunction>(xrGetD3D11GraphicsRequirementsKHR);
962   } else if (strcmp(name, "xrGetActionStateFloat") == 0) {
963     *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetActionStateFloat);
964   } else if (strcmp(name, "xrGetActionStateBoolean") == 0) {
965     *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetActionStateBoolean);
966   } else if (strcmp(name, "xrGetActionStateVector2f") == 0) {
967     *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetActionStateVector2f);
968   } else if (strcmp(name, "xrGetActionStatePose") == 0) {
969     *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetActionStatePose);
970   } else if (strcmp(name, "xrGetCurrentInteractionProfile") == 0) {
971     *function =
972         reinterpret_cast<PFN_xrVoidFunction>(xrGetCurrentInteractionProfile);
973   } else if (strcmp(name, "xrGetReferenceSpaceBoundsRect") == 0) {
974     *function =
975         reinterpret_cast<PFN_xrVoidFunction>(xrGetReferenceSpaceBoundsRect);
976   } else if (strcmp(name, "xrGetSystem") == 0) {
977     *function = reinterpret_cast<PFN_xrVoidFunction>(xrGetSystem);
978   } else if (strcmp(name, "xrLocateSpace") == 0) {
979     *function = reinterpret_cast<PFN_xrVoidFunction>(xrLocateSpace);
980   } else if (strcmp(name, "xrLocateViews") == 0) {
981     *function = reinterpret_cast<PFN_xrVoidFunction>(xrLocateViews);
982   } else if (strcmp(name, "xrPollEvent") == 0) {
983     *function = reinterpret_cast<PFN_xrVoidFunction>(xrPollEvent);
984   } else if (strcmp(name, "xrReleaseSwapchainImage") == 0) {
985     *function = reinterpret_cast<PFN_xrVoidFunction>(xrReleaseSwapchainImage);
986   } else if (strcmp(name, "xrSuggestInteractionProfileBindings") == 0) {
987     *function = reinterpret_cast<PFN_xrVoidFunction>(
988         xrSuggestInteractionProfileBindings);
989   } else if (strcmp(name, "xrStringToPath") == 0) {
990     *function = reinterpret_cast<PFN_xrVoidFunction>(xrStringToPath);
991   } else if (strcmp(name, "xrPathToString") == 0) {
992     *function = reinterpret_cast<PFN_xrVoidFunction>(xrPathToString);
993   } else if (strcmp(name, "xrSyncActions") == 0) {
994     *function = reinterpret_cast<PFN_xrVoidFunction>(xrSyncActions);
995   } else if (strcmp(name, "xrWaitFrame") == 0) {
996     *function = reinterpret_cast<PFN_xrVoidFunction>(xrWaitFrame);
997   } else if (strcmp(name, "xrWaitSwapchainImage") == 0) {
998     *function = reinterpret_cast<PFN_xrVoidFunction>(xrWaitSwapchainImage);
999   } else {
1000     return XR_ERROR_FUNCTION_UNSUPPORTED;
1001   }
1002 
1003   return XR_SUCCESS;
1004 }