st/oxr: Add a path store

This commit is contained in:
Jakob Bornecrantz 2019-04-05 13:44:21 +01:00
parent 9173e1d31c
commit 77b3b7b840
4 changed files with 295 additions and 0 deletions

View file

@ -25,6 +25,7 @@ set(OXR_SOURCE_FILES
oxr/oxr_logger.h
oxr/oxr_messenger.c
oxr/oxr_objects.h
oxr/oxr_path.c
oxr/oxr_session.c
oxr/oxr_session_gl.c
oxr/oxr_session_vk.c

View file

@ -41,6 +41,12 @@ oxr_instance_destroy(struct oxr_logger *log, struct oxr_handle_base *hb)
struct xrt_prober *prober = inst->prober;
struct xrt_device *dev = inst->system.device;
oxr_path_destroy_all(log, inst);
if (inst->path_store != NULL) {
u_hashset_destroy(&inst->path_store);
}
if (dev != NULL) {
dev->destroy(dev);
inst->system.device = NULL;
@ -65,9 +71,18 @@ oxr_instance_create(struct oxr_logger *log,
struct oxr_instance **out_instance)
{
struct oxr_instance *inst = NULL;
int h_ret;
OXR_ALLOCATE_HANDLE_OR_RETURN(log, inst, OXR_XR_DEBUG_INSTANCE,
oxr_instance_destroy, NULL);
h_ret = u_hashset_create(&inst->path_store);
if (h_ret != 0) {
free(inst);
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE,
"Failed to create hashset");
}
inst->prober = xrt_create_prober();
struct xrt_device *dev =

View file

@ -13,6 +13,7 @@
#include "xrt/xrt_compositor.h"
#include "xrt/xrt_vulkan_includes.h"
#include "xrt/xrt_openxr_includes.h"
#include "util/u_hashset.h"
#ifdef __cplusplus
extern "C" {
@ -42,6 +43,7 @@ extern "C" {
#define OXR_XR_DEBUG_INSTANCE (*(uint64_t *)"oxrinst\0")
#define OXR_XR_DEBUG_SESSION (*(uint64_t *)"oxrsess\0")
#define OXR_XR_DEBUG_SPACE (*(uint64_t *)"oxrspac\0")
#define OXR_XR_DEBUG_PATH (*(uint64_t *)"oxrpath\0")
#define OXR_XR_DEBUG_ACTION (*(uint64_t *)"oxracti\0")
#define OXR_XR_DEBUG_SWAPCHAIN (*(uint64_t *)"oxrswap\0")
#define OXR_XR_DEBUG_ACTIONSET (*(uint64_t *)"oxraset\0")
@ -149,6 +151,60 @@ oxr_instance_convert_timespec_to_time(struct oxr_logger *log,
XrTime *time);
#endif // XR_USE_TIMESPEC
/*
*
* oxr_path.c
*
*/
void *
oxr_path_get_attached(struct oxr_logger *log,
struct oxr_instance *inst,
XrPath path);
/*!
* Get the path for the given string if it exists, or create it if it does not.
*/
XrResult
oxr_path_get_or_create(struct oxr_logger *log,
struct oxr_instance *inst,
const char *str,
size_t length,
XrPath *out_path);
/*!
* Only get the path for the given string if it exists.
*/
XrResult
oxr_path_only_get(struct oxr_logger *log,
struct oxr_instance *inst,
const char *str,
size_t length,
XrPath *out_path);
/*!
* Get a pointer and length of the internal string.
*
* The pointer has the same life time as the instance. The length is the number
* of valid characters, not including the null termination character (but a
* extra null byte is always reserved at the end so can strings can be given
* to functions expecting null terminated strings).
*/
XrResult
oxr_path_get_string(struct oxr_logger *log,
struct oxr_instance *inst,
XrPath path,
const char **out_str,
size_t *out_length);
/*!
* Destroy all paths that the instance has created.
*/
void
oxr_path_destroy_all(struct oxr_logger *log, struct oxr_instance *inst);
/*
*
* oxr_session.c
@ -538,6 +594,9 @@ struct oxr_instance
struct time_state *timekeeping;
//! Path store, for looking up paths.
struct u_hashset *path_store;
// Event queue.
struct oxr_event *last_event;
struct oxr_event *next_event;

View file

@ -0,0 +1,220 @@
// Copyright 2019, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Holds path related functions.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup oxr_main
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "math/m_api.h"
#include "util/u_misc.h"
#include "oxr_objects.h"
#include "oxr_logger.h"
/*!
* Internal representation of a path, item follows this struct in memory and
* that in turn is followed by the string.
*
* @ingroup oxr_main
*/
struct oxr_path
{
uint64_t debug;
void *attached;
};
/*
*
* Helpers
*
*/
static inline struct oxr_path *
oxr_path(XrPath path)
{
return (struct oxr_path *)path;
}
static inline XrPath
to_xr_path(struct oxr_path *path)
{
return (XrPath)path;
}
static inline struct u_hashset_item *
get_item(struct oxr_path *path)
{
return (struct u_hashset_item *)&path[1];
}
static inline struct oxr_path *
from_item(struct u_hashset_item *item)
{
return &((struct oxr_path *)item)[-1];
}
/*
*
* Static functions.
*
*/
static XrResult
oxr_allocate_path(struct oxr_logger *log,
struct oxr_instance *inst,
const char *str,
size_t length,
struct oxr_path **out_path)
{
struct u_hashset_item *item = NULL;
struct oxr_path *path = NULL;
size_t size = 0;
int ret;
size += sizeof(struct oxr_path); // Main path object.
size += sizeof(struct u_hashset_item); // Embedded hashset item.
size += length; // String.
size += 1; // Null terminate it.
// Now allocate and setup the path.
path = U_CALLOC_WITH_CAST(struct oxr_path, size);
if (path == NULL) {
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE,
"Failed to allocate path");
}
path->debug = OXR_XR_DEBUG_PATH;
// Setup the item.
item = get_item(path);
item->hash = math_hash_string(str, length);
item->length = length;
// Yes a const cast! D:
char *store = (char *)item->c_str;
for (size_t i = 0; i < length; i++) {
store[i] = str[i];
}
store[length] = '\0';
// Insert and return.
ret = u_hashset_insert_item(inst->path_store, item);
if (ret) {
free(path);
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE,
"Failed to insert item");
}
*out_path = path;
return XR_SUCCESS;
}
/*
*
* "Exported" functions.
*
*/
void *
oxr_path_get_attached(struct oxr_logger *log,
struct oxr_instance *inst,
XrPath xr_path)
{
if (xr_path == XR_NULL_PATH) {
return NULL;
}
return oxr_path(xr_path)->attached;
}
XrResult
oxr_path_get_or_create(struct oxr_logger *log,
struct oxr_instance *inst,
const char *str,
size_t length,
XrPath *out_path)
{
struct u_hashset_item *item;
struct oxr_path *path;
XrResult ret;
int h_ret;
// Look it up the instance path store.
h_ret = u_hashset_find_str(inst->path_store, str, length, &item);
if (h_ret == 0) {
*out_path = to_xr_path(from_item(item));
return XR_SUCCESS;
}
// Create the path since it was not found.
ret = oxr_allocate_path(log, inst, str, length, &path);
if (ret != XR_SUCCESS) {
return ret;
}
*out_path = to_xr_path(path);
return XR_SUCCESS;
}
XrResult
oxr_path_only_get(struct oxr_logger *log,
struct oxr_instance *inst,
const char *str,
size_t length,
XrPath *out_path)
{
struct u_hashset_item *item;
int h_ret;
// Look it up the instance path store.
h_ret = u_hashset_find_str(inst->path_store, str, length, &item);
if (h_ret == 0) {
*out_path = to_xr_path(from_item(item));
return XR_SUCCESS;
}
*out_path = XR_NULL_PATH;
return XR_SUCCESS;
}
XrResult
oxr_path_get_string(struct oxr_logger *log,
struct oxr_instance *inst,
XrPath xr_path,
const char **out_str,
size_t *out_length)
{
struct oxr_path *path = oxr_path(xr_path);
*out_str = get_item(path)->c_str;
*out_length = get_item(path)->length;
return XR_SUCCESS;
}
void
destroy_callback(struct u_hashset_item *item, void *priv)
{
struct oxr_path *path = from_item(item);
free(path);
}
void
oxr_path_destroy_all(struct oxr_logger *log,
struct oxr_instance *inst)
{
u_hashset_clear_and_call_for_each(inst->path_store, destroy_callback,
inst);
}