diff --git a/src/xrt/state_trackers/oxr/oxr_instance.c b/src/xrt/state_trackers/oxr/oxr_instance.c index 90476ed8f..572ec2d45 100644 --- a/src/xrt/state_trackers/oxr/oxr_instance.c +++ b/src/xrt/state_trackers/oxr/oxr_instance.c @@ -60,11 +60,8 @@ oxr_instance_destroy(struct oxr_logger *log, struct oxr_handle_base *hb) u_var_remove_root((void *)inst); oxr_binding_destroy_all(log, inst); - oxr_path_destroy_all(log, inst); - if (inst->path_store != NULL) { - u_hashset_destroy(&inst->path_store); - } + oxr_path_destroy(log, inst); for (size_t i = 0; i < inst->system.num_xdevs; i++) { oxr_xdev_destroy(&inst->system.xdevs[i]); @@ -102,7 +99,7 @@ oxr_instance_create(struct oxr_logger *log, { struct oxr_instance *inst = NULL; struct xrt_device *xdevs[NUM_XDEVS] = {0}; - int h_ret, xinst_ret; + int xinst_ret; XrResult ret; OXR_ALLOCATE_HANDLE_OR_RETURN(log, inst, OXR_XR_DEBUG_INSTANCE, @@ -117,11 +114,10 @@ oxr_instance_create(struct oxr_logger *log, oxr_sdl2_hack_create(&inst->hack); /* ---- HACK ---- */ - h_ret = u_hashset_create(&inst->path_store); - if (h_ret != 0) { + ret = oxr_path_init(log, inst); + if (ret != XR_SUCCESS) { free(inst); - return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, - "Failed to create hashset"); + return 0; } // Cache certain often looked up paths. diff --git a/src/xrt/state_trackers/oxr/oxr_objects.h b/src/xrt/state_trackers/oxr/oxr_objects.h index 1636698fd..aeadf4652 100644 --- a/src/xrt/state_trackers/oxr/oxr_objects.h +++ b/src/xrt/state_trackers/oxr/oxr_objects.h @@ -209,6 +209,12 @@ oxr_instance_convert_timespec_to_time(struct oxr_logger *log, * */ +/*! + * Initialize the path system. + */ +XrResult +oxr_path_init(struct oxr_logger *log, struct oxr_instance *inst); + void * oxr_path_get_attached(struct oxr_logger *log, struct oxr_instance *inst, @@ -250,10 +256,10 @@ oxr_path_get_string(struct oxr_logger *log, size_t *out_length); /*! - * Destroy all paths that the instance has created. + * Destroy the path system and all paths that the instance has created. */ void -oxr_path_destroy_all(struct oxr_logger *log, struct oxr_instance *inst); +oxr_path_destroy(struct oxr_logger *log, struct oxr_instance *inst); /* @@ -941,6 +947,12 @@ struct oxr_instance //! Path store, for looking up paths. struct u_hashset *path_store; + //! Mapping from ID to path. + struct oxr_path **path_array; + //! Total length of path array. + size_t path_array_length; + //! Number of paths in the array (0 is always null). + size_t path_num; // Event queue. struct oxr_event *last_event; diff --git a/src/xrt/state_trackers/oxr/oxr_path.c b/src/xrt/state_trackers/oxr/oxr_path.c index 39930ccf9..476bf036b 100644 --- a/src/xrt/state_trackers/oxr/oxr_path.c +++ b/src/xrt/state_trackers/oxr/oxr_path.c @@ -27,6 +27,7 @@ struct oxr_path { uint64_t debug; + XrPath id; void *attached; }; @@ -37,16 +38,10 @@ struct oxr_path * */ -static inline struct oxr_path * -oxr_path(XrPath path) -{ - return XRT_CAST_OXR_HANDLE_TO_PTR(struct oxr_path *, path); -} - static inline XrPath to_xr_path(struct oxr_path *path) { - return XRT_CAST_PTR_TO_OXR_HANDLE(XrPath, path); + return path->id; } static inline struct u_hashset_item * @@ -68,6 +63,31 @@ from_item(struct u_hashset_item *item) * */ +static XrResult +oxr_ensure_array_length(struct oxr_logger *log, + struct oxr_instance *inst, + XrPath *out_id) +{ + size_t num = inst->path_num + 1; + + if (num < inst->path_array_length) { + *out_id = inst->path_num++; + return XR_SUCCESS; + } + + size_t new_size = inst->path_array_length; + while (new_size < num) { + new_size += 64; + } + + U_ARRAY_REALLOC_OR_FREE(inst->path_array, struct oxr_path *, new_size); + inst->path_array_length = new_size; + + *out_id = inst->path_num++; + + return XR_SUCCESS; +} + static XrResult oxr_allocate_path(struct oxr_logger *log, struct oxr_instance *inst, @@ -113,11 +133,25 @@ oxr_allocate_path(struct oxr_logger *log, "Failed to insert item"); } + oxr_ensure_array_length(log, inst, &path->id); + inst->path_array[path->id] = path; + *out_path = path; return XR_SUCCESS; } +struct oxr_path * +get_path_or_null(struct oxr_logger *log, + struct oxr_instance *inst, + XrPath xr_path) +{ + if (xr_path >= inst->path_array_length) { + return NULL; + } + + return inst->path_array[xr_path]; +} /* * @@ -130,11 +164,12 @@ oxr_path_get_attached(struct oxr_logger *log, struct oxr_instance *inst, XrPath xr_path) { - if (xr_path == XR_NULL_PATH) { + struct oxr_path *path = get_path_or_null(log, inst, xr_path); + if (path == NULL) { return NULL; } - return oxr_path(xr_path)->attached; + return path->attached; } XrResult @@ -195,7 +230,10 @@ oxr_path_get_string(struct oxr_logger *log, const char **out_str, size_t *out_length) { - struct oxr_path *path = oxr_path(xr_path); + struct oxr_path *path = get_path_or_null(log, inst, xr_path); + if (path == NULL) { + return XR_ERROR_PATH_INVALID; + } *out_str = get_item(path)->c_str; *out_length = get_item(path)->length; @@ -211,9 +249,39 @@ destroy_callback(struct u_hashset_item *item, void *priv) free(path); } -void -oxr_path_destroy_all(struct oxr_logger *log, struct oxr_instance *inst) +XrResult +oxr_path_init(struct oxr_logger *log, struct oxr_instance *inst) { + int h_ret = u_hashset_create(&inst->path_store); + if (h_ret != 0) { + return oxr_error(log, XR_ERROR_RUNTIME_FAILURE, + "Failed to create hashset"); + } + + size_t new_size = 64; + U_ARRAY_REALLOC_OR_FREE(inst->path_array, struct oxr_path *, new_size); + inst->path_array_length = new_size; + inst->path_num = 1; // Reserve space for XR_NULL_PATH + + return XR_SUCCESS; +} + +void +oxr_path_destroy(struct oxr_logger *log, struct oxr_instance *inst) +{ + if (inst->path_array != NULL) { + free(inst->path_array); + } + + inst->path_array = NULL; + inst->path_num = 0; + inst->path_array_length = 0; + + if (inst->path_store == NULL) { + return; + } + u_hashset_clear_and_call_for_each(inst->path_store, destroy_callback, inst); + u_hashset_destroy(&inst->path_store); }