Monado OpenXR Runtime
oxr_api_verify.h
Go to the documentation of this file.
1 // Copyright 2018-2024, Collabora, Ltd.
2 // SPDX-License-Identifier: BSL-1.0
3 /*!
4  * @file
5  * @brief File for verifying app input into api functions.
6  * @author Jakob Bornecrantz <jakob@collabora.com>
7  * @author Korcan Hussein <korcan.hussein@collabora.com>
8  * @ingroup oxr_api
9  */
10 
11 #pragma once
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 
18 #define OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_thing, THING, name, lookup) \
19  do { \
20  oxr_log_init(log, name); \
21  if (thing == XR_NULL_HANDLE) { \
22  return oxr_error(log, XR_ERROR_HANDLE_INVALID, "(" #thing " == NULL)"); \
23  } \
24  new_thing = (struct oxr_thing *)((uintptr_t)thing); \
25  if (new_thing->handle.debug != OXR_XR_DEBUG_##THING) { \
26  return oxr_error(log, XR_ERROR_HANDLE_INVALID, "(" #thing " == %p)", (void *)new_thing); \
27  } \
28  if (new_thing->handle.state != OXR_HANDLE_STATE_LIVE) { \
29  return oxr_error(log, XR_ERROR_HANDLE_INVALID, "(" #thing " == %p) state == %s", \
30  (void *)new_thing, oxr_handle_state_to_string(new_thing->handle.state)); \
31  } \
32  oxr_log_set_instance(log, lookup); \
33  } while (0)
34 
35 #define OXR_VERIFY_SET(log, arg, new_arg, oxr_thing, THING) \
36  do { \
37  if (arg == XR_NULL_HANDLE) { \
38  return oxr_error(log, XR_ERROR_HANDLE_INVALID, "(" #arg " == NULL)"); \
39  } \
40  new_arg = (struct oxr_thing *)((uintptr_t)arg); \
41  if (new_arg->handle.debug != OXR_XR_DEBUG_##THING) { \
42  return oxr_error(log, XR_ERROR_HANDLE_INVALID, "(" #arg " == %p)", (void *)new_arg); \
43  } \
44  } while (0)
45 
46 
47 /*!
48  * @addtogroup oxr_api
49  * @{
50  */
51 
52 // clang-format off
53 #define OXR_VERIFY_INSTANCE_AND_INIT_LOG(log, thing, new_thing, name) \
54  OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_instance, INSTANCE, name, new_thing)
55 #define OXR_VERIFY_MESSENGER_AND_INIT_LOG(log, thing, new_thing, name) \
56  OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_messenger, MESSENGER, name, new_thing->inst)
57 #define OXR_VERIFY_SESSION_AND_INIT_LOG(log, thing, new_thing, name) \
58  OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_session, SESSION, name, new_thing->sys->inst)
59 #define OXR_VERIFY_SPACE_AND_INIT_LOG(log, thing, new_thing, name) \
60  OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_space, SPACE, name, new_thing->sess->sys->inst)
61 #define OXR_VERIFY_ACTION_AND_INIT_LOG(log, thing, new_thing, name) \
62  OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_action, ACTION, name, new_thing->act_set->inst)
63 #define OXR_VERIFY_SWAPCHAIN_AND_INIT_LOG(log, thing, new_thing, name) \
64  OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_swapchain, SWAPCHAIN, name, new_thing->sess->sys->inst)
65 #define OXR_VERIFY_ACTIONSET_AND_INIT_LOG(log, thing, new_thing, name) \
66  OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_action_set, ACTIONSET, name, new_thing->inst)
67 #define OXR_VERIFY_HAND_TRACKER_AND_INIT_LOG(log, thing, new_thing, name) \
68  OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_hand_tracker, HTRACKER, name, new_thing->sess->sys->inst)
69 #define OXR_VERIFY_FORCE_FEEDBACK_AND_INIT_LOG(log, thing, new_thing, name) \
70  OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_force_feedback, FFB, name, new_thing->sess->sys->inst)
71 #define OXR_VERIFY_PASSTHROUGH_AND_INIT_LOG(log, thing, new_thing, name) \
72  OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_passthrough, PASSTHROUGH, name, new_thing->sess->sys->inst)
73 #define OXR_VERIFY_PASSTHROUGH_LAYER_AND_INIT_LOG(log, thing, new_thing, name) \
74  OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_passthrough_layer, PASSTHROUGH_LAYER, name, new_thing->sess->sys->inst)
75 #define OXR_VERIFY_FACE_TRACKER_HTC_AND_INIT_LOG(log, thing, new_thing, name) \
76  OXR_VERIFY_AND_SET_AND_INIT(log, thing, new_thing, oxr_facial_tracker_htc, FTRACKER, name, new_thing->sess->sys->inst)
77 // clang-format on
78 
79 #define OXR_VERIFY_INSTANCE_NOT_NULL(log, arg, new_arg) OXR_VERIFY_SET(log, arg, new_arg, oxr_instance, INSTANCE);
80 #define OXR_VERIFY_MESSENGER_NOT_NULL(log, arg, new_arg) OXR_VERIFY_SET(log, arg, new_arg, oxr_messenger, MESSENGER);
81 #define OXR_VERIFY_SESSION_NOT_NULL(log, arg, new_arg) OXR_VERIFY_SET(log, arg, new_arg, oxr_session, SESSION);
82 #define OXR_VERIFY_SPACE_NOT_NULL(log, arg, new_arg) OXR_VERIFY_SET(log, arg, new_arg, oxr_space, SPACE);
83 #define OXR_VERIFY_ACTION_NOT_NULL(log, arg, new_arg) OXR_VERIFY_SET(log, arg, new_arg, oxr_action, ACTION);
84 #define OXR_VERIFY_SWAPCHAIN_NOT_NULL(log, arg, new_arg) OXR_VERIFY_SET(log, arg, new_arg, oxr_swapchain, SWAPCHAIN);
85 #define OXR_VERIFY_ACTIONSET_NOT_NULL(log, arg, new_arg) OXR_VERIFY_SET(log, arg, new_arg, oxr_action_set, ACTIONSET);
86 
87 /*!
88  * Checks if a required extension is enabled.
89  *
90  * mixed_case_name should be the extension name without the XR_ prefix.
91  */
92 #define OXR_VERIFY_EXTENSION(log, inst, mixed_case_name) \
93  do { \
94  if (!(inst)->extensions.mixed_case_name) { \
95  return oxr_error((log), XR_ERROR_FUNCTION_UNSUPPORTED, \
96  "Requires XR_" #mixed_case_name " extension enabled"); \
97  } \
98  } while (false)
99 
100 /*!
101  * Checks if either one of two required extensions is enabled.
102  *
103  * mixed_case_name should be the extension name without the XR_ prefix.
104  */
105 #define OXR_VERIFY_EXTENSIONS_OR(log, inst, mixed_case_name1, mixed_case_name2) \
106  do { \
107  if (!(inst)->extensions.mixed_case_name1 && !(inst)->extensions.mixed_case_name2) { \
108  return oxr_error((log), XR_ERROR_FUNCTION_UNSUPPORTED, \
109  "Requires XR_" #mixed_case_name1 "or XR_" #mixed_case_name2 \
110  " extension enabled"); \
111  } \
112  } while (false)
113 
114 #define OXR_VERIFY_ARG_NOT_NULL(log, arg) \
115  do { \
116  if (arg == NULL) { \
117  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "(" #arg " == NULL)"); \
118  } \
119  } while (false)
120 
121 #define OXR_VERIFY_ARG_NOT_ZERO(log, arg) \
122  do { \
123  if (arg == 0) { \
124  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "(" #arg " == 0) must be non-zero"); \
125  } \
126  } while (false)
127 
128 #define OXR_VERIFY_ARG_ZERO(log, arg) \
129  do { \
130  if (arg != 0) { \
131  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "(" #arg " == 0) must be zero"); \
132  } \
133  } while (false)
134 
135 #define OXR_VERIFY_ARG_TYPE_CAN_BE_NULL(log, arg, type_enum) \
136  do { \
137  if (arg != NULL && arg->type != type_enum) { \
138  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "(" #arg "->type == %u)", arg->type); \
139  } \
140  } while (false)
141 
142 #define OXR_VERIFY_ARG_TYPE_AND_NOT_NULL(log, arg, type_enum) \
143  do { \
144  if (arg == NULL) { \
145  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "(" #arg " == NULL)"); \
146  } \
147  OXR_VERIFY_ARG_TYPE_CAN_BE_NULL(log, arg, type_enum); \
148  } while (false)
149 
150 /*!
151  * Must only be used with full typed arrays, aka non-basetyped arrays like that
152  * passed into xrEnumerateSwapchainImages.
153  */
154 #define OXR_VERIFY_ARG_ARRAY_ELEMENT_TYPE(log, array, index, type_enum) \
155  do { \
156  if ((array)[index].type != type_enum) { \
157  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \
158  "(" #array "[%u]->type == 0x%08x) expected 0x%08x", index, \
159  (array)[index].type, type_enum); \
160  } \
161  } while (false)
162 
163 #define OXR_VERIFY_SUBACTION_PATHS(log, count, paths) \
164  do { \
165  if (count > 0 && paths == NULL) { \
166  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \
167  "(" #count ") is not zero but " #paths " is NULL"); \
168  } \
169  } while (false)
170 
171 #define OXR_VERIFY_ARG_SINGLE_LEVEL_FIXED_LENGTH_PATH(log, path) \
172  do { \
173  XrResult verify_ret = oxr_verify_fixed_size_single_level_path(log, path, ARRAY_SIZE(path), #path); \
174  if (verify_ret != XR_SUCCESS) { \
175  return verify_ret; \
176  } \
177  } while (false)
178 
179 #define OXR_VERIFY_ARG_LOCALIZED_NAME(log, string) \
180  do { \
181  XrResult verify_ret = oxr_verify_localized_name(log, string, ARRAY_SIZE(string), #string); \
182  if (verify_ret != XR_SUCCESS) { \
183  return verify_ret; \
184  } \
185  } while (false)
186 
187 #define OXR_VERIFY_POSE(log, p) \
188  do { \
189  if (!math_quat_validate((struct xrt_quat *)&p.orientation)) { \
190  return oxr_error(log, XR_ERROR_POSE_INVALID, "(" #p ".orientation) is not a valid quat"); \
191  } \
192  \
193  if (!math_vec3_validate((struct xrt_vec3 *)&p.position)) { \
194  return oxr_error(log, XR_ERROR_POSE_INVALID, "(" #p ".position) is not valid"); \
195  } \
196  } while (false)
197 
198 #define OXR_VERIFY_VIEW_CONFIG_TYPE(log, inst, view_conf) \
199  do { \
200  XrResult verify_ret = oxr_verify_view_config_type(log, inst, view_conf, #view_conf); \
201  if (verify_ret != XR_SUCCESS) { \
202  return verify_ret; \
203  } \
204  } while (false)
205 
206 #define OXR_VERIFY_VIEW_INDEX(log, index) \
207  do { \
208  if (index > 2) { \
209  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \
210  "Invalid view index %d, only 2 views supported", index); \
211  } \
212  } while (false)
213 
214 #define OXR_VERIFY_SWAPCHAIN_USAGE_FLAGS_NOT_MUTUALLY_EXCLUSIVE(log, flags, mutually_exclusive_a, \
215  mutually_exclusive_b) \
216  do { \
217  if (((flags) & (mutually_exclusive_a)) != 0 && ((flags) & (mutually_exclusive_b)) != 0) { \
218  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \
219  "(" #flags ") Swapchain usage flags " #mutually_exclusive_a \
220  " and " #mutually_exclusive_b \
221  " are mutually exclusive in this graphics API"); \
222  } \
223  } while (false)
224 
225 #define OXR_VERIFY_SESSION_NOT_LOST(log, sess) \
226  do { \
227  if (sess->has_lost) { \
228  return oxr_error(log, XR_ERROR_SESSION_LOST, "Session is lost"); \
229  } \
230  } while (false)
231 
232 #define OXR_VERIFY_SESSION_RUNNING(log, sess) \
233  do { \
234  if (!sess->has_begun) { \
235  return oxr_error(log, XR_ERROR_SESSION_NOT_RUNNING, "Session is not running"); \
236  } \
237  } while (false)
238 
239 #define OXR_VERIFY_PASSTHROUGH_FLAGS(log, flags) \
240  if (flags == 0 || \
241  (flags & (XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB | XR_PASSTHROUGH_LAYER_DEPTH_BIT_FB)) == 0) \
242  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \
243  "flags is not a valid combination of XrPassthroughFlagBitsFB values");
244 
245 #define OXR_VERIFY_PASSTHROUGH_LAYER_PURPOSE(log, purpose) \
246  if ((purpose != XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB && \
247  purpose != XR_PASSTHROUGH_LAYER_PURPOSE_PROJECTED_FB && \
248  purpose != XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS_FB && \
249  purpose != XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS_FB)) \
250  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \
251  "purpose is not a valid XrPassthroughLayerPurposeFB value");
252 
253 #define OXR_VERIFY_PASSTHROUGH_LAYER_STYLE(log, style) \
254  do { \
255  uint32_t duplicate_check = 0; \
256  const XrPassthroughStyleFB *next = style->next; \
257  while (next) { \
258  if (next->type != XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB && \
259  next->type != XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB && \
260  next->type != XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB) \
261  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \
262  "style next structure chain contains invalid pointers"); \
263  if ((next->type & duplicate_check) != 0) \
264  return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, \
265  "style next structure chain contains duplicate items"); \
266  duplicate_check |= next->type; \
267  next = (const XrPassthroughStyleFB *)next->next; \
268  } \
269  } while (false)
270 
271 /*
272  *
273  * Implementation in oxr_verify.cpp
274  *
275  */
276 
277 XrResult
278 oxr_verify_full_path_c(struct oxr_logger *log, const char *path, const char *name);
279 
280 /*!
281  * Verify a full path.
282  *
283  * Length not including zero terminator character but must be there.
284  */
285 XrResult
286 oxr_verify_full_path(struct oxr_logger *log, const char *path, size_t length, const char *name);
287 
288 /*!
289  * Verify a single path level that sits inside of a fixed sized array.
290  */
291 XrResult
293  const char *path,
294  uint32_t array_size,
295  const char *name);
296 
297 /*!
298  * Verify an arbitrary UTF-8 string that sits inside of a fixed sized array.
299  */
300 XrResult
301 oxr_verify_localized_name(struct oxr_logger * /*log*/, const char *string, uint32_t array_size, const char *name);
302 
303 /*!
304  * Verify a set of subaction paths for action creation.
305  */
306 XrResult
308  struct oxr_instance *inst,
309  uint32_t countSubactionPaths,
310  const XrPath *subactionPaths,
311  const char *variable);
312 
313 /*!
314  * Verify a set of subaction paths for action sync.
315  */
316 XrResult
318  const struct oxr_instance *inst,
319  const struct oxr_action_set *act_set,
320  XrPath path,
321  uint32_t index);
322 
323 /*!
324  * Verify a set of subaction paths for action state get.
325  */
326 XrResult
328  struct oxr_instance *inst,
329  XrPath path,
330  const struct oxr_subaction_paths *act_subaction_paths,
331  struct oxr_subaction_paths *out_subaction_paths,
332  const char *variable);
333 
334 XrResult
335 oxr_verify_extensions(struct oxr_logger *log, const struct oxr_extension_status *extensions);
336 
337 XrResult
338 oxr_verify_view_config_type(struct oxr_logger *log,
339  struct oxr_instance *inst,
340  XrViewConfigurationType view_conf,
341  const char *view_conf_name);
342 
343 XrResult
344 oxr_verify_XrSessionCreateInfo(struct oxr_logger * /*log*/,
345  const struct oxr_instance * /*inst*/,
346  const XrSessionCreateInfo * /*createInfo*/);
347 
348 #if defined(XR_USE_PLATFORM_XLIB) && defined(XR_USE_GRAPHICS_API_OPENGL)
349 XrResult
350 oxr_verify_XrGraphicsBindingOpenGLXlibKHR(struct oxr_logger * /*log*/, const XrGraphicsBindingOpenGLXlibKHR * /*next*/);
351 #endif // defined(XR_USE_PLATFORM_XLIB) && defined(XR_USE_GRAPHICS_API_OPENGL)
352 
353 #if defined(XR_USE_PLATFORM_WIN32) && defined(XR_USE_GRAPHICS_API_OPENGL)
354 XrResult
355 oxr_verify_XrGraphicsBindingOpenGLWin32KHR(struct oxr_logger * /*log*/,
356  const XrGraphicsBindingOpenGLWin32KHR * /*next*/);
357 #endif // defined(XR_USE_PLATFORM_WIN32) && defined(XR_USE_GRAPHICS_API_OPENGL)
358 
359 #if defined(XR_USE_GRAPHICS_API_VULKAN)
360 XrResult
361 oxr_verify_XrGraphicsBindingVulkanKHR(struct oxr_logger * /*log*/, const XrGraphicsBindingVulkanKHR * /*next*/);
362 #endif // defined(XR_USE_GRAPHICS_API_VULKAN)
363 
364 #if defined(XR_USE_PLATFORM_EGL) && defined(XR_USE_GRAPHICS_API_OPENGL)
365 XrResult
366 oxr_verify_XrGraphicsBindingEGLMNDX(struct oxr_logger *log, const XrGraphicsBindingEGLMNDX *next);
367 #endif // defined(XR_USE_PLATFORM_EGL) && defined(XR_USE_GRAPHICS_API_OPENGL)
368 
369 #if defined(XR_USE_PLATFORM_ANDROID) && defined(XR_USE_GRAPHICS_API_OPENGL_ES)
370 XrResult
371 oxr_verify_XrGraphicsBindingOpenGLESAndroidKHR(struct oxr_logger *, const XrGraphicsBindingOpenGLESAndroidKHR *);
372 #endif // defined(XR_USE_PLATFORM_ANDROID) &&
373  // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
374 
375 #if defined(XR_USE_GRAPHICS_API_D3D11)
376 XrResult
377 oxr_verify_XrGraphicsBindingD3D11KHR(struct oxr_logger *, const XrGraphicsBindingD3D11KHR *);
378 #endif // defined(XR_USE_GRAPHICS_API_D3D11)
379 
380 #if defined(XR_USE_GRAPHICS_API_D3D12)
381 XrResult
382 oxr_verify_XrGraphicsBindingD3D12KHR(struct oxr_logger *, const XrGraphicsBindingD3D12KHR *);
383 #endif // defined(XR_USE_GRAPHICS_API_D3D12)
384 
385 #ifdef XR_EXT_dpad_binding
386 XrResult
387 oxr_verify_XrInteractionProfileDpadBindingEXT(struct oxr_logger *,
388  const XrInteractionProfileDpadBindingEXT *,
389  const char *error_prefix);
390 #endif // XR_EXT_dpad_binding
391 
392 /*!
393  * @}
394  */
395 
396 
397 #ifdef __cplusplus
398 }
399 #endif
XrResult oxr_verify_subaction_paths_create(struct oxr_logger *log, struct oxr_instance *inst, uint32_t countSubactionPaths, const XrPath *subactionPaths, const char *variable)
Verify a set of subaction paths for action creation.
XrResult oxr_verify_subaction_path_sync(struct oxr_logger *log, const struct oxr_instance *inst, const struct oxr_action_set *act_set, XrPath path, uint32_t index)
Verify a set of subaction paths for action sync.
XrResult oxr_verify_fixed_size_single_level_path(struct oxr_logger *, const char *path, uint32_t array_size, const char *name)
Verify a single path level that sits inside of a fixed sized array.
Definition: oxr_verify.c:64
XrResult oxr_verify_subaction_path_get(struct oxr_logger *log, struct oxr_instance *inst, XrPath path, const struct oxr_subaction_paths *act_subaction_paths, struct oxr_subaction_paths *out_subaction_paths, const char *variable)
Verify a set of subaction paths for action state get.
XrResult oxr_verify_full_path(struct oxr_logger *log, const char *path, size_t length, const char *name)
Verify a full path.
Definition: oxr_verify.c:139
XrResult oxr_verify_localized_name(struct oxr_logger *, const char *string, uint32_t array_size, const char *name)
Verify an arbitrary UTF-8 string that sits inside of a fixed sized array.
Definition: oxr_verify.c:95
A group of actions.
Definition: oxr_objects.h:2352
Structure tracking which extensions are enabled for a given instance.
Definition: oxr_objects.h:1491
Main object that ties everything together.
Definition: oxr_objects.h:1504
Logger struct that lives on the stack, one for each call client call.
Definition: oxr_logger.h:40
A parsed equivalent of a list of sub-action paths.
Definition: oxr_objects.h:1935